{
  "openapi": "3.0.0",
  "paths": {
    "/v1/balance": {
      "get": {
        "operationId": "Balance_getBalance",
        "summary": "Get platform balance breakdown",
        "description": "Returns tenant ledger totals plus seller obligations (pending + available) and platformAvailableVes. Incoming credits are held for 24h (`heldVes`, `nextReleaseAt`) before payouts can spend them.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformBalanceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Balance"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/balance/transactions": {
      "get": {
        "operationId": "Balance_listTransactions",
        "summary": "List balance movements",
        "description": "Every movement in your VES balance, newest first: payments, fees, payouts, reversals, card chargebacks, adjustments, seller transfers and conversions. The sum of `amountVes` over all movements equals `ledgerNetVes` from GET /v1/balance (and minus `reserveVes` and `heldVes`, `availableVes`), so you can reconcile your own ledger automatically. Movements still under the 24h balance hold carry `availableAt`. Page with `cursor`.",
        "parameters": [
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "ISO 8601, exclusive (createdAt).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "ISO 8601, inclusive (createdAt).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "payoutId",
            "required": false,
            "in": "query",
            "description": "Only movements of this payout.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paymentId",
            "required": false,
            "in": "query",
            "description": "Only movements of this payment.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "description": "One or more types (repeat or comma-separate).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "payment",
                  "fee",
                  "payment_reversal",
                  "fee_reversal",
                  "payout",
                  "payout_reversal",
                  "chargeback",
                  "chargeback_fee",
                  "chargeback_reversal",
                  "adjustment",
                  "seller_transfer",
                  "seller_transfer_reversal",
                  "conversion",
                  "conversion_reversal",
                  "merchant_payout_fee"
                ]
              }
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "`nextCursor` from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100, default 50.",
            "schema": {
              "example": 50,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceTransactionListDto"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_data` — a parameter is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Balance"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/webhooks": {
      "post": {
        "operationId": "Webhooks_createWebhook",
        "summary": "Register a webhook endpoint",
        "description": "The signing secret is returned only on creation. Delivery currently uses one attempt with a 10-second timeout.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Webhooks_listWebhooks",
        "summary": "List webhook endpoints",
        "description": "Signing secrets are never included.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookEndpointDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/webhooks/{id}": {
      "patch": {
        "operationId": "Webhooks_updateWebhook",
        "summary": "Update a webhook endpoint",
        "description": "Update url, subscribed events, and/or active status. Providing events replaces the full subscription list. The signing secret cannot be changed.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointDto"
                }
              }
            }
          },
          "400": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "Webhooks_deleteWebhook",
        "summary": "Delete a webhook endpoint and its delivery history",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteWebhookResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payouts": {
      "post": {
        "operationId": "Payouts_create",
        "summary": "Create a simple merchant payout",
        "description": "Credits a verified merchant Pago Móvil method with an exact VES `monto`. `externalRef` is the idempotency key (same payload → 200 replay; conflicting payload → 409 `external_ref_conflict`). Requires an active merchant and a verified payout method.\n\n**New-account limit.** While a tenant or merchant is new (first 30 days), money-out is capped per rolling 24h (USD equivalent, default $300). A payout that would exceed it is still created (201) and its funds are reserved, but it is returned with `status: \"awaiting_approval\"` and `holdReason: \"NEW_ACCOUNT_LIMIT\"` and is not sent to the bank until VEX Pay reviews it. Approval sends it as usual (`payout.completed` / `payout.failed`); a rejection fails it with `failureCode: \"rejected_new_account_limit\"` and returns the funds to the balance.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePayoutDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of an existing payout with the same externalRef and payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutResponseDto"
                }
              }
            }
          },
          "201": {
            "description": "Payout created (new externalRef).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "external_ref_conflict, merchant_inactive, or related business conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payouts"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Payouts_list",
        "summary": "List payouts",
        "description": "Cursor-paginated list (`items`, `nextCursor`). Newest-first within the page. Use `status` to filter pending settlements.",
        "parameters": [
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Optional status filter. `awaiting_approval` lists payouts held for VEX Pay review.",
            "schema": {
              "enum": [
                "pending",
                "awaiting_approval",
                "completed",
                "failed"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "Opaque cursor from a previous `nextCursor`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size 1–100 (default 25).",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payouts"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payouts/instant": {
      "post": {
        "operationId": "Payouts_createInstant",
        "summary": "Instant crédito to the verified tenant payout account",
        "description": "Credits the tenant’s verified Pago Móvil account (see GET /v1/tenant/payout-account). Requires a verified account that is eligible (first verify is immediate; destination changes require a completed 1 business-day cooling period). `monto` is the gross VES withdrawn from available balance; the bank receives monto minus feePercent.\n\n**New-account limit.** While a tenant or merchant is new (first 30 days), money-out is capped per rolling 24h (USD equivalent, default $300). A payout that would exceed it is still created (201) and its funds are reserved, but it is returned with `status: \"awaiting_approval\"` and `holdReason: \"NEW_ACCOUNT_LIMIT\"` and is not sent to the bank until VEX Pay reviews it. Approval sends it as usual (`payout.completed` / `payout.failed`); a rejection fails it with `failureCode: \"rejected_new_account_limit\"` and returns the funds to the balance.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInstantPayoutDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of an existing instant credit with the same externalRef and payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutResponseDto"
                }
              }
            }
          },
          "201": {
            "description": "Instant credit created (new externalRef).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "external_ref_conflict when the same key is reused with a different payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payouts"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payouts/batch": {
      "post": {
        "operationId": "Payouts_createBatch",
        "summary": "Create a split payout batch (per-item results)",
        "description": "Creates or replays a batch keyed by batch-level `externalRef`. Each item is processed independently; failures are returned inline with status `failed` and do not abort siblings. Item-level `externalRef` values remain individually idempotent.\n\n**New-account limit.** While a tenant or merchant is new (first 30 days), money-out is capped per rolling 24h (USD equivalent, default $300). A payout that would exceed it is still created (201) and its funds are reserved, but it is returned with `status: \"awaiting_approval\"` and `holdReason: \"NEW_ACCOUNT_LIMIT\"` and is not sent to the bank until VEX Pay reviews it. Approval sends it as usual (`payout.completed` / `payout.failed`); a rejection fails it with `failureCode: \"rejected_new_account_limit\"` and returns the funds to the balance.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePayoutBatchDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of an existing batch with the same payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutBatchResponseDto"
                }
              }
            }
          },
          "201": {
            "description": "New batch processed (may include mixed completed/pending/failed items).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutBatchResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "Batch external_ref_conflict when the same batch key is reused with a different payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payouts"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payouts/by-ref/{externalRef}": {
      "get": {
        "operationId": "Payouts_getByRef",
        "summary": "Get payout details by externalRef",
        "description": "Lookup by the tenant-supplied idempotency / correlation key.",
        "parameters": [
          {
            "name": "externalRef",
            "required": true,
            "in": "path",
            "schema": {
              "example": "po_9c21",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No payout with that externalRef for this tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payouts"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payouts/{id}": {
      "get": {
        "operationId": "Payouts_getById",
        "summary": "Get payout details and status by id",
        "description": "Use to poll pending payouts until status becomes completed or failed.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payouts"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/tenant/payout-account": {
      "get": {
        "operationId": "TenantPayoutAccount_get",
        "summary": "Get the tenant instant-credit payout account",
        "description": "Returns the single Pago Móvil destination used for POST /v1/payouts/instant, including eligibility (`pending_verification` | `verifying` | `cooling` | `eligible` | …). When none is configured yet, returns JSON `null` (HTTP 200) — create one with PUT/POST.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configured account, or `null` when not set up yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPayoutAccountResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tenant payout account"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "put": {
        "operationId": "TenantPayoutAccount_upsert",
        "summary": "Create or update the tenant payout account",
        "description": "Upserts cédula/RIF + phone + bank. Changing any destination field clears verification; the next successful verify applies a 1 business-day cooling period (first-time verify unlocks immediately).",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertTenantPayoutAccountDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPayoutAccountResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tenant payout account"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "post": {
        "operationId": "TenantPayoutAccount_upsertPost",
        "summary": "Create or update the tenant payout account (POST alias)",
        "description": "Same as PUT /v1/tenant/payout-account — provided so create flows can use POST.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertTenantPayoutAccountDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPayoutAccountResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tenant payout account"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/tenant/payout-account/verify/start": {
      "post": {
        "operationId": "TenantPayoutAccount_startVerify",
        "summary": "Start micro-deposit verification for the tenant payout account",
        "description": "Sends two secret 0.XX crédito inmediato deposits (same pattern as merchant verify). Confirm with POST /v1/tenant/payout-account/verify.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPayoutAccountVerifyStartResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "already_verified or locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "credit_rejected or payout_account_missing (save an account first).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tenant payout account"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/tenant/payout-account/verify": {
      "post": {
        "operationId": "TenantPayoutAccount_confirmVerify",
        "summary": "Confirm micro-deposit amounts",
        "description": "On success the account becomes verified. First-time verify is immediately eligible; re-verify after a destination change enters a 1 business-day cooling period (`payoutEligibleAt`).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmTenantPayoutAccountVerifyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPayoutAccountVerifyConfirmResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "amounts_mismatch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "410": {
            "description": "window_expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "payout_account_missing or not_ready.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tenant payout account"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/debit/otp": {
      "post": {
        "operationId": "R4Operations_generarOtp",
        "summary": "Send a debit authorization code to the customer",
        "description": "Asks the payer bank to SMS an OTP for débito inmediato. Amounts are in VES. On success the response `code` is typically `202`. Collect the OTP from your customer, then call POST /v1/payments/debit with the same payer fields. Test-mode tenants use a simulated débito — use the rotating code from Portal → Sandbox.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateDebitOtpDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OTP request accepted by the payer bank (typically code `202`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DebitOtpResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/debit": {
      "post": {
        "operationId": "R4Operations_debitoInmediato",
        "summary": "Execute an immediate debit",
        "description": "Charges the payer after they provide the bank OTP. `ACCP` = accepted (payment.completed webhook). `AC00` = pending — the gateway polls ConsultarOperaciones until ACCP or a reject code, then fires payment.completed or payment.failed. Optional `externalRef` is stored for recovery via GET /v1/payments/by-ref/:externalRef (correlation, not an idempotency key). A new charge whose `externalRef` already has a COMPLETED payment for this tenant is refused with 409 `external_ref_already_paid` (body: `code` EXTERNAL_REF_ALREADY_PAID, `paymentId` of the paid payment, `externalRef`). Retries after FAILED / CANCELED / REVERSED / expired are allowed; repeated amounts are fine. Response always includes `paymentId` for the DEBITO_INMEDIATO payment record. Test-mode tenants simulate débito; sandbox codes and test cards are in Portal → Sandbox.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImmediateDebitDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network payload plus VEXPay `paymentId` (and `externalRef` when sent).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImmediateDebitResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "externalRef already has a COMPLETED payment (external_ref_already_paid; body includes paymentId).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/operations/{id}": {
      "get": {
        "operationId": "R4Operations_consultarOperacion",
        "summary": "Poll a pending payment operation",
        "description": "Manual ConsultarOperaciones lookup. Prefer relying on gateway auto-poll + webhooks for AC00 débito/crédito. When a PENDING payment transitions, the same payment.* webhooks fire (idempotent). Persist `id`/`Id` from execute responses.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Network operation id from a prior debit/credit response (`id` or `Id`).",
            "schema": {
              "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current network status for the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/R4OperationResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/operations/poll": {
      "post": {
        "operationId": "R4Operations_pollOperation",
        "summary": "Manually poll a pending débito, payout, or verification deposit",
        "description": "Forces one ConsultarOperaciones cycle for a tenant-owned entity. Same settlement path as the gateway minute cron (webhooks fire when status changes). Prefer auto-poll in production.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManualOperationPollDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManualOperationPollResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "Entity not found for this tenant, or missing operation id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/credit": {
      "post": {
        "operationId": "R4Operations_creditoInmediato",
        "summary": "Execute an immediate credit by phone",
        "description": "Credits a beneficiary Pago Móvil destination (banco + cedula + telefono) for a VES `monto`. Response may be `ACCP` or pending `AC00` (auto-polled).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImmediateCreditDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/R4OperationResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/credit/account": {
      "post": {
        "operationId": "R4Operations_creditoCuentas",
        "summary": "Execute a credit to a bank account",
        "description": "Credits a 20-digit Venezuelan account (`cuenta`) for a VES `monto`. Response may be `ACCP` or pending `AC00`.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountCreditDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/R4OperationResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/credit/disburse": {
      "post": {
        "operationId": "R4Operations_dispersarCredito",
        "summary": "Disburse credits by phone",
        "description": "Splits a completed inbound PAGO_MOVIL payment (matched by `referencia`) across multiple phone recipients. `monto` must match that payment’s vesAmount; sum of `personas[].montoPart` must equal `monto`. Each recipient is credited via CreditoInmediato. Returns 404 if no matching completed payment; 409 if already dispersed.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreditDisbursementDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditDisbursementResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No completed PAGO_MOVIL payment found for the given referencia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "The matched payment was already dispersed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/payouts": {
      "post": {
        "operationId": "R4Operations_dispersarPagos",
        "summary": "Disburse payments to bank accounts",
        "description": "Account-based multi-beneficiary dispersion (R4pagos). Distinct from merchant payouts at POST /v1/payouts. `fecha` is MM/DD/YYYY; only the last 9 digits of `referencia` are sent to the bank. Sum of `personas[].montoPart` must equal `monto`.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PayoutDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPayoutDispersionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/change": {
      "post": {
        "operationId": "R4Operations_ejecutarVuelto",
        "summary": "Send change to a customer",
        "description": "Sends a small VES “vuelto” (change) to the customer’s Pago Móvil destination after a purchase.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePaymentDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangePaymentResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business-rule failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "This method (débito or crédito) is not enabled on this account, or live mode is not activated (`live_mode_not_activated`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The banking network rejected the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "Advanced payments are not available in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Advanced payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/crypto/balance": {
      "get": {
        "operationId": "Crypto_getBalance",
        "summary": "Get a stablecoin balance",
        "description": "Amount available for payouts and amount reserved by in-flight payouts, in one stablecoin (`currency`, default USDT), from the VEXPay ledger. USDT and USDC balances are separate.",
        "parameters": [
          {
            "name": "currency",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "USDT",
                "USDC"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CryptoBalanceDto"
                }
              }
            }
          },
          "400": {
            "description": "`unsupported_currency`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — USDC is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Crypto"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/crypto/balances": {
      "get": {
        "operationId": "Crypto_getBalances",
        "summary": "Get all stablecoin balances",
        "description": "One balance per stablecoin (USDT, USDC).",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CryptoBalancesDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Crypto"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/crypto/deposit-addresses": {
      "post": {
        "operationId": "Crypto_createDepositAddress",
        "summary": "Get or create a deposit address",
        "description": "Returns the static address for one of your customers, one stablecoin (`currency`, default USDT) and one network. Calling again returns the same address. Deposits are credited to that stablecoin's balance (net of the fee) and reported with `payment.completed` carrying `customerRef` and `currency`. A deposit of the other stablecoin to this address is credited in the stablecoin that arrived when your account accepts it on that network.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDepositAddressDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositAddressDto"
                }
              }
            }
          },
          "400": {
            "description": "`unsupported_currency`, `unsupported_network` or invalid `customerRef`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — that stablecoin is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Crypto"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/crypto/networks": {
      "get": {
        "operationId": "Crypto_listNetworks",
        "summary": "List networks",
        "description": "Enabled networks for one stablecoin (`currency`, default USDT) with the payout fee and whether a payout of `amount` can be sent now.",
        "parameters": [
          {
            "name": "amountUsdt",
            "required": false,
            "in": "query",
            "description": "Alias of `amount`.",
            "schema": {
              "example": "50.00",
              "type": "string"
            }
          },
          {
            "name": "currency",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "USDT",
                "USDC"
              ],
              "type": "string"
            }
          },
          {
            "name": "amount",
            "required": false,
            "in": "query",
            "schema": {
              "example": "50.00",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CryptoNetworkDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`unsupported_currency`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — that stablecoin is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Crypto"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/crypto/payouts": {
      "post": {
        "operationId": "Crypto_createPayout",
        "summary": "Send a stablecoin to an external address",
        "description": "Debits amount + fee from your balance of `currency` (default USDT); USDC payouts never draw on USDT and vice versa. Payouts within your limits are sent automatically; larger ones wait for review. Completion arrives as `payout.completed` (with `txHash`) or `payout.failed` (refunded). A payout to one of your own deposit addresses settles instantly inside VEXPay with no network fee.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCryptoPayoutDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of an existing payout.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CryptoPayoutDto"
                }
              }
            }
          },
          "201": {
            "description": "Payout created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CryptoPayoutDto"
                }
              }
            }
          },
          "400": {
            "description": "`unsupported_currency`, `unsupported_network`, `invalid_address` or `invalid_data`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — that stablecoin is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused` with a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "`insufficient_balance` or `amount_below_minimum`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Crypto"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/crypto/payouts/{id}": {
      "get": {
        "operationId": "Crypto_getPayout",
        "summary": "Retrieve a stablecoin payout",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CryptoPayoutDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Crypto"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/channels": {
      "get": {
        "operationId": "CopPayments_channels",
        "summary": "List COP channels",
        "description": "The COP channels you can use right now in this mode, with what each needs. When `pse` is listed, `pseBanks` gives the bank codes for `pse.bankCode`. When a channel needs terms acceptance, show the buyer the `terms` links before you send `buyer.termsAccepted: true`. `card` is listed with `checkoutOnly: true`: take it through the hosted checkout.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopChannelsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — COP is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/payments": {
      "post": {
        "operationId": "CopPayments_create",
        "summary": "Create a COP payment",
        "description": "Collect Colombian pesos with Bre-B (QR code or transfer key from any Colombian bank app), Nequi (push to the buyer's app), Daviplata (SMS code or redirect), PSE and Bancolombia (redirect to the buyer's bank) or Bancolombia QR. See `GET /v1/cop/channels` for what you can use and what each needs. The response says what the buyer must do next. The payment completes asynchronously: listen for `payment.completed` / `payment.failed`, or read it back. Send an `Idempotency-Key` to retry safely.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCopPaymentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopPaymentDto"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_data` (names the field), `amount_below_minimum`, `amount_out_of_range`, or `channel_requires_checkout` (card).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — COP is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "502": {
            "description": "`processor_unavailable` — the payment network did not answer; read the payment before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`method_unavailable` — the channel is not available right now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/payments/{id}": {
      "get": {
        "operationId": "CopPayments_get",
        "summary": "Get a COP payment",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopPaymentDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/payments/{id}/otp": {
      "post": {
        "operationId": "CopPayments_submitOtp",
        "summary": "Complete a Daviplata payment",
        "description": "Submit the code the buyer received by SMS.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitCopOtpDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopPaymentDto"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_otp` — the payment stays pending until it expires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`invalid_state` — not a pending Daviplata payment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/payments/{id}/cancel": {
      "post": {
        "operationId": "CopPayments_cancel",
        "summary": "Cancel a pending COP payment",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopPaymentDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`invalid_state` — the payment is not pending.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/payments/{id}/refund": {
      "post": {
        "operationId": "CopPayments_refund",
        "summary": "Refund a COP payment in full",
        "description": "Bre-B, Nequi and Daviplata payments with an SMS code: within 96 hours of completion. Card: within the void window (24 hours). Other channels answer `refund_not_supported`. The amount credited to you is debited from your COP balance and the fee is returned. Partial refunds are not supported.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopPaymentDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`invalid_state`, `refund_not_supported` (the channel has no refunds), `refund_window_expired` or `insufficient_balance`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/cop/balance": {
      "get": {
        "operationId": "CopPayments_balance",
        "summary": "Get your COP balance",
        "description": "Whole pesos available for payout and reserved by payouts in progress.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopBalanceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`method_not_allowed` — COP is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "COP"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/conversions/settings": {
      "get": {
        "operationId": "ConversionSettings_get",
        "summary": "Get conversion settings",
        "description": "Your spreads, minimum, daily caps, which currencies you can convert from, and auto-convert.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionSettingsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "patch": {
        "operationId": "ConversionSettings_update",
        "summary": "Update auto-convert",
        "description": "Set the share (0–100, whole number; 0 = off) of each completed COP pay-in that is converted to USDT automatically. Applies to pay-ins completed after the change. Spreads, minimums and caps can only be changed by VEXPay.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConversionSettingsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionSettingsDto"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_data` — unknown field or percent outside 0–100.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`conversions_not_enabled` — COP conversions are not allowed for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/conversions/quotes": {
      "post": {
        "operationId": "Conversions_createQuote",
        "summary": "Quote a VES or COP → USDT conversion",
        "description": "Locks a rate for 60 seconds. Choose `sourceCurrency` (`VES`, the default, or `COP`), then send the amount you want to spend (`sourceAmount`; VES may also use `sourceAmountVes`) or the USDT you want to receive (`targetAmountUsdt`). The rate is the market USDT rate in that currency plus your spread; USDT is rounded down to the cent, VES up to the cent and COP up to the whole peso.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateConversionQuoteDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionQuoteDto"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_amount` — send exactly one positive amount.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`conversions_not_enabled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "`amount_below_minimum` or `insufficient_balance`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`rate_unavailable` — no current market rate; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/conversions": {
      "post": {
        "operationId": "Conversions_create",
        "summary": "Convert VES or COP to USDT",
        "description": "Accepts a quote. The VES or COP is debited from your available balance immediately (`conversion.created`) and the conversion is `PENDING` until VEXPay delivers the USDT to your USDT balance (`conversion.completed`). A pending conversion can be canceled; if VEXPay cannot fulfil it, it is canceled and the amount is returned (`conversion.canceled`). In test mode conversions complete immediately. Send an `Idempotency-Key` header to retry safely.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateConversionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "`conversions_not_enabled` or `live_mode_not_activated`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "Unknown quote.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`quote_used`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "410": {
            "description": "`quote_expired` — request a new quote.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "`insufficient_balance` or `daily_limit_exceeded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Conversions_list",
        "summary": "List conversions",
        "description": "Newest first, cursor-paginated.",
        "parameters": [
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "PENDING",
                "COMPLETED",
                "CANCELED"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          },
          {
            "name": "sourceCurrency",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "VES",
                "COP"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionListDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/conversions/{id}": {
      "get": {
        "operationId": "Conversions_get",
        "summary": "Get a conversion",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/conversions/{id}/cancel": {
      "post": {
        "operationId": "Conversions_cancel",
        "summary": "Cancel a pending conversion",
        "description": "Returns the VES or COP to your available balance.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`conversion_not_cancelable` — already completed or canceled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Conversions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/banks": {
      "get": {
        "operationId": "Payments_getBanks",
        "summary": "List supported banks (with logos)",
        "description": "Returns the listed Venezuelan bank catalog: SIMF `code`, `name`, `services`, and `logoUrl`. `logoUrl` is a public 100×100 PNG when available (otherwise null) — use it in bank selectors so customers can recognize their bank. Hidden/unlisted banks are omitted. Prefer this endpoint over hard-coded bank lists.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BankResponseDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments",
          "Banks"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/quote": {
      "get": {
        "operationId": "Payments_getQuote",
        "summary": "Quote a USD amount in VES at your account's Bolívar rate",
        "description": "Returns `rate`/`rateSource` (your account's Bolívar rate: the official BCV rate, or the market rate if you chose it) and `vesAmount` = usdAmount × rate, which is what a payment created now would charge. `bcvRate` is always the official VEX FX BCV rate; medianRate/medianVesAmount come from available BCV sources (VEX FX and bank rates when available). A MARKET account gets 503 rate_unavailable when no fresh market rate exists.",
        "parameters": [
          {
            "name": "usdAmount",
            "required": true,
            "in": "query",
            "description": "Positive USD amount to convert. Must be a finite number greater than zero.",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "rate/vesAmount are authoritative for settlement; bcvRate is the official rate; medianRate/medianVesAmount are for display. sources includes per-source rates or errors.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/c2p/request": {
      "post": {
        "operationId": "Payments_requestC2p",
        "summary": "Create a pending C2P payment intent and request bank OTP when supported",
        "description": "Creates a PENDING intent. When externalRef is provided, any other PENDING C2P intent for the same tenant + externalRef is canceled (superseded) and payment.canceled is fired. Pending C2P intents expire after 15 minutes. When the routed bank supports it, VEXPay also asks the payer bank to SMS a token to the customer (`otpRequested: true`). Collect that token, then execute with POST /v1/payments/c2p. A new charge whose `externalRef` already has a COMPLETED payment for this tenant is refused with 409 `external_ref_already_paid` (body: `code` EXTERNAL_REF_ALREADY_PAID, `paymentId` of the paid payment, `externalRef`). Retries after FAILED / CANCELED / REVERSED / expired are allowed; repeated amounts are fine.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/C2pRequestDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/C2pIntentResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "externalRef already has a COMPLETED payment (external_ref_already_paid; body includes paymentId).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/c2p": {
      "post": {
        "operationId": "Payments_executeC2p",
        "summary": "Execute a C2P charge",
        "description": "Charges the customer with the bank-issued token. Prefer including `intentId` from POST /v1/payments/c2p/request. Returns a PaymentReceiptDto; subscribe to payment.completed / payment.failed for async confirmation when applicable. `externalRef` is correlation (not an idempotency key — use Idempotency-Key for retries). A new charge whose `externalRef` already has a COMPLETED payment for this tenant is refused with 409 `external_ref_already_paid` (body: `code` EXTERNAL_REF_ALREADY_PAID, `paymentId` of the paid payment, `externalRef`). Retries after FAILED / CANCELED / REVERSED / expired are allowed; repeated amounts are fine. On an intent, only another COMPLETED payment with its externalRef blocks it.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/C2pPaymentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment receipt (status PENDING or COMPLETED).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentReceiptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "The supplied intent does not exist or is no longer pending.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "externalRef already has a COMPLETED payment (external_ref_already_paid; body includes paymentId).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The provider rejected the charge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/vpos": {
      "post": {
        "operationId": "Payments_executeVpos",
        "summary": "Execute a VPOS card charge",
        "description": "BNC only. Submit PAN/CVV only from a PCI-compliant server environment. Pass usdAmount (VES derived at your Bolívar rate: BCV, or market if you chose it) or vesAmount (locks the bolívar charge; USD derived). Returns PaymentReceiptDto with optional cardLast4 / cardBrand. Never log full card data. Carding defense: attempts our risk checks decline are refused without contacting the bank (429, code CARD_VELOCITY_BLOCKED, generic message). Retry later or use another payment method. Test cards: with a Test key, the VPOS test cards listed at /vpos#test-card return fixed outcomes (approvals, bank declines with their G-codes, a chargeback) without contacting the bank; with a Live key they are refused with 400 test_card_in_live_mode. A new charge whose `externalRef` already has a COMPLETED payment for this tenant is refused with 409 `external_ref_already_paid` (body: `code` EXTERNAL_REF_ALREADY_PAID, `paymentId` of the paid payment, `externalRef`). Retries after FAILED / CANCELED / REVERSED / expired are allowed; repeated amounts are fine.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VposPaymentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentReceiptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or a VPOS test card sent with a Live key (test_card_in_live_mode).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "externalRef already has a COMPLETED payment (external_ref_already_paid; body includes paymentId).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The provider rejected the charge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Carding defense tripped: 3 distinct cards already failed for this payer in the last 30 minutes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payment-methods": {
      "get": {
        "operationId": "Payments_listPaymentMethods",
        "summary": "List the bolívar payment methods your account can take",
        "description": "Which VES pay-in methods are available to your account right now: `pago_movil` (customer-sent Pago Móvil, also requires the receiving account to be configured), `c2p` (bank debit with the customer's OTP) and `vpos` (card). Use it to decide which options to show; cache it for a few minutes.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodsResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/pago-movil/receiving-account": {
      "get": {
        "operationId": "Payments_getPagoMovilReceivingAccount",
        "summary": "Get the Pago Móvil account your customers pay into",
        "description": "Where a customer must send a Pago Móvil for POST /v1/payments/pago-movil/verify to find it: bank, phone and identification of the receiving account. Resolved with the same provider routing as verify (your enabled/default providers; no override). When a detail is not configured the response is still 200 with `configured: false` and `missing` listing it — do not offer Pago Móvil to customers until `configured` is true.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagoMovilReceivingAccountDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/pago-movil/verify": {
      "post": {
        "operationId": "Payments_verifyPagoMovil",
        "summary": "Verify a customer-originated Pago Móvil transfer",
        "description": "Matches a customer-supplied bank `reference` (and optional `dateMovement` YYYY-MM-DD) against bank movements for the quoted USD amount. Returns PaymentReceiptDto when found. Depending on the receiving bank, confirmation is a live query or the bank's own notification to VEXPay — right after a transfer, a not-found can resolve within seconds, so retry with backoff.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PagoMovilVerifyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentReceiptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/by-ref/{externalRef}": {
      "get": {
        "operationId": "Payments_getPaymentByRef",
        "summary": "Find the latest payment with an external reference",
        "description": "externalRef is not unique and does not prevent duplicate payments.",
        "parameters": [
          {
            "name": "externalRef",
            "required": true,
            "in": "path",
            "schema": {
              "example": "order-1042",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentReceiptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/{id}": {
      "get": {
        "operationId": "Payments_getPayment",
        "summary": "Get a payment by ID",
        "description": "Returns the full PaymentReceiptDto for any method (C2P, VPOS, PAGO_MOVIL, DEBITO_INMEDIATO).",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentReceiptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payments/{id}/reverse": {
      "post": {
        "operationId": "Payments_reversePayment",
        "summary": "Reverse a completed C2P payment",
        "description": "Reversal is supported for C2P payments only.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentReceiptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants": {
      "post": {
        "operationId": "Merchants_create",
        "summary": "Register a merchant (optionally with an initial Pago Móvil payout method)",
        "description": "Provide bankCode + phone together to create the first payout method, or omit both to create a merchant shell. `externalRef` is the idempotency key (same payload → 200 replay; conflicting payload → 409 `external_ref_conflict`). Responses with an empty payoutMethods[] include `message` explaining that no payout method exists yet — add one via POST /v1/merchants/:id/payout-methods before verify or payout.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMerchantDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay or shell update / method attach for an existing externalRef.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantResponseDto"
                }
              }
            }
          },
          "201": {
            "description": "Merchant created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "external_ref_conflict when the same key is reused with a different payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Merchants_listOrGetByRef",
        "summary": "List merchants or lookup by externalRef",
        "description": "Without query params, returns a paginated list (`items`, `nextCursor`). Pass `externalRef` for a single-merchant lookup. Optional filters: `status`, `isActive` (true|false), `cursor`, `limit` (1–100, default 25). For payout pickers use `status=verified&isActive=true`. Each merchant includes `payoutMethods[]`; top-level `bankCode`/`destination` mirror the default method.",
        "parameters": [
          {
            "name": "externalRef",
            "required": false,
            "in": "query",
            "description": "When set, returns a single MerchantResponseDto instead of the paginated list.",
            "schema": {
              "example": "usr_7f3a",
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Filter by mirrored default-method status.",
            "schema": {
              "enum": [
                "pending_verification",
                "verifying",
                "verified",
                "rejected"
              ],
              "type": "string"
            }
          },
          {
            "name": "isActive",
            "required": false,
            "in": "query",
            "description": "Filter by active flag.",
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "Opaque cursor from a previous `nextCursor`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size 1–100 (default 25). Ignored when externalRef is set.",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated MerchantListResponseDto by default, or a single MerchantResponseDto when `externalRef` is provided.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/MerchantListResponseDto"
                    },
                    {
                      "$ref": "#/components/schemas/MerchantResponseDto"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "Returned when externalRef is set and no merchant matches.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/payout-methods": {
      "get": {
        "operationId": "Merchants_listPayoutMethods",
        "summary": "List payout methods for a merchant",
        "description": "Returns every Pago Móvil destination (`items[]`) with status, isDefault, and masked destination. Prefer this over reading only top-level merchant bankCode/destination.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Merchant id.",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutMethodListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "post": {
        "operationId": "Merchants_addPayoutMethod",
        "summary": "Add a Pago Móvil payout method to a merchant",
        "description": "Registers another bankCode + phone. The first method created with the merchant is default; additional methods start as non-default and pending_verification until micro-deposit confirm.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePayoutMethodDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutMethodResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/payout-methods/{methodId}/default": {
      "post": {
        "operationId": "Merchants_setDefaultPayoutMethod",
        "summary": "Set a payout method as the merchant default",
        "description": "Clears isDefault on other methods. Top-level merchant bankCode/destination mirror this method. Payouts without payoutMethodId prefer the default verified method.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "methodId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutMethodResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/payout-methods/{methodId}": {
      "delete": {
        "operationId": "Merchants_deletePayoutMethod",
        "summary": "Delete a payout method",
        "description": "Removes a Pago Móvil destination. If it was the default, another method is promoted (verified preferred). Historical payouts keep bank/phone snapshots; their payoutMethodId is cleared.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "methodId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Payout method deleted."
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/payout-methods/{methodId}/verify/start": {
      "post": {
        "operationId": "Merchants_startVerifyMethod",
        "summary": "Start micro-deposit verification for a payout method",
        "description": "Sends two secret 0.XX micro-deposits to that method’s Pago Móvil destination. Amounts are never returned in the API response, logs, or webhooks. Ask the merchant what they received, then confirm with POST …/verify within 2 days.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "methodId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Verification session started; amounts are intentionally omitted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyStartResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "Verification locked or already in progress.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/payout-methods/{methodId}/verify": {
      "post": {
        "operationId": "Merchants_confirmVerifyMethod",
        "summary": "Confirm micro-deposit amounts for a payout method",
        "description": "Submit the two exact 0.XX amounts the merchant received (order-insensitive). On success the method becomes verified and can be selected via payoutMethodId on POST /v1/payouts.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "methodId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmMerchantVerifyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyConfirmResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "Wrong amounts, locked, or no active verification session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/balance": {
      "get": {
        "operationId": "Merchants_getBalance",
        "summary": "Get seller pending/available balance",
        "description": "Returns Connect-style pendingVes and availableVes for the merchant under this platform tenant.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantBalanceDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/transfers": {
      "post": {
        "operationId": "Merchants_transfer",
        "summary": "Transfer platform float to seller pending balance",
        "description": "Debits tenant available (SELLER_TRANSFER) and credits merchant pending. When sellerHoldBusinessDays is 0, funds release to available immediately.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMerchantTransferDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantBalanceDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}": {
      "get": {
        "operationId": "Merchants_getById",
        "summary": "Get merchant details, payout methods, and verification status",
        "description": "Includes payoutMethods[] and top-level bankCode/destination mirrors of the default method.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "patch": {
        "operationId": "Merchants_update",
        "summary": "Update merchant flags (active / auto-payout / commission)",
        "description": "Soft off-switch for payouts, optional autoPayoutEnabled for cron payouts from available balance, and the merchant's negotiated applicationFeePercent (null = tenant default commission).",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMerchantDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "Merchants_remove",
        "summary": "Delete a merchant",
        "description": "Hard-deletes the merchant and its payout methods when there is no payout history. Frees externalRef for re-registration. Returns 409 merchant_has_payouts (with payoutCount) if payouts exist — use PATCH isActive:false instead.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteMerchantResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "Merchant not found for this tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "merchant_has_payouts — merchant has payout history; deactivate instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/audit-events": {
      "get": {
        "operationId": "Merchants_listAuditEvents",
        "summary": "Merchant compliance / lifecycle audit trail",
        "description": "Append-only events (MERCHANT_CREATED, RIF_SUBMITTED, MERCHANT_ACTIVATED, CAPABILITY_ENABLED, MERCHANT_UPDATED, MERCHANT_RESTRICTED, …), oldest first.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantAuditEventListDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/verify/start": {
      "post": {
        "operationId": "Merchants_startVerify",
        "summary": "Start micro-deposit verification (default payout method)",
        "description": "Legacy helper: verifies the default payout method. Prefer POST /v1/merchants/:id/payout-methods/:methodId/verify/start.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyStartResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/merchants/{id}/verify": {
      "post": {
        "operationId": "Merchants_confirmVerify",
        "summary": "Confirm micro-deposit amounts (active / default payout method)",
        "description": "Legacy helper: confirms the active verification session or default method. Prefer POST /v1/merchants/:id/payout-methods/:methodId/verify.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmMerchantVerifyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyConfirmResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Merchants"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/checkout/sessions": {
      "post": {
        "operationId": "CheckoutSessions_create",
        "summary": "Create a checkout session",
        "description": "Creates a single-purchase checkout and returns its hosted `url` plus a one-time `clientSecret` for embedding with @vexpay/js. The secret is returned only here — VEXPay stores just its hash. Outcomes arrive as `payment.*` webhooks carrying `checkoutSession: { id, reference, metadata }`.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCheckoutSessionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSessionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "invalid_data (e.g. a non-https origin on a live tenant).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "amount_below_minimum",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Checkout Sessions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/checkout/sessions/{id}": {
      "get": {
        "operationId": "CheckoutSessions_retrieve",
        "summary": "Retrieve a checkout session",
        "description": "Current status and, once a payment exists, its `paymentId`. Never returns `clientSecret`.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "example": "cs_4f0c6f1e2b7d4c1a9e3f5a6b7c8d9e0f",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSessionResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Checkout Sessions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/products": {
      "post": {
        "operationId": "Products_create",
        "summary": "Create a product",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProductDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Products_list",
        "summary": "List products (cursor pagination)",
        "parameters": [
          {
            "name": "active",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/products/{id}": {
      "get": {
        "operationId": "Products_get",
        "summary": "Get a product and its payment links",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "patch": {
        "operationId": "Products_update",
        "summary": "Update a product",
        "description": "Send only the fields to change. Pass \"\" to clear description / imageUrl.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProductDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "Products_remove",
        "summary": "Delete a product",
        "description": "Hard-deletes the product and its payment links. Returns 409 product_has_sales if any checkout session was paid.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "product_has_sales",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/products/{id}/links": {
      "post": {
        "operationId": "Products_createLink",
        "summary": "Create a payment link for a product",
        "description": "Omit slug to auto-generate one from the product name. 409 slug_taken if a provided slug is in use.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentLinkDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "slug_taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Products_listLinks",
        "summary": "List payment links for a product",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payment-links/{id}": {
      "get": {
        "operationId": "PaymentLinks_get",
        "summary": "Get a payment link",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "patch": {
        "operationId": "PaymentLinks_update",
        "summary": "Update a payment link",
        "description": "Enable/disable it (status), toggle allowQuantity, set maxQuantity or redirectUrl.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePaymentLinkDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "PaymentLinks_remove",
        "summary": "Delete a payment link",
        "description": "Returns 409 product_has_sales if a checkout session on this link was paid — disable it instead.",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "product_has_sales",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Products"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/notifications/test": {
      "post": {
        "operationId": "Notifications_sendTest",
        "summary": "Send a test event to subscribed webhook endpoints",
        "description": "Fires a `notification.test` event to every active webhook endpoint subscribed to that event (or all events, depending on your subscription list). Use this to validate URL reachability and HMAC signature verification before going live. Returns 202 Accepted with `{ sent, event, tenantId }`. Limited to 10 calls per tenant per 10 minutes (429 beyond that).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Test event queued/delivered to matching endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationTestResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or inactive tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 10 test notifications in 10 minutes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/customers": {
      "post": {
        "operationId": "Customers_create",
        "summary": "Create a billing customer",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomerDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Customers"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Customers_list",
        "summary": "List customers (newest first, cursor pagination)",
        "parameters": [
          {
            "name": "email",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Customers"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/customers/{id}": {
      "get": {
        "operationId": "Customers_retrieve",
        "summary": "Retrieve a customer",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Customers"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "post": {
        "operationId": "Customers_update",
        "summary": "Update a customer (null clears a field)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Customers"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "Customers_remove",
        "summary": "Delete a customer with no live subscriptions",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedObjectResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "customer_has_active_subscriptions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Customers"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/prices": {
      "post": {
        "operationId": "Prices_create",
        "summary": "Create a recurring price on a product",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePriceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "amount_below_minimum",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Prices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Prices_list",
        "summary": "List prices (cursor pagination)",
        "parameters": [
          {
            "name": "product",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "active",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Prices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/prices/{id}": {
      "get": {
        "operationId": "Prices_retrieve",
        "summary": "Retrieve a price",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Prices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "post": {
        "operationId": "Prices_update",
        "summary": "Update a price (active, nickname, metadata only)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePriceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Prices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/subscriptions": {
      "post": {
        "operationId": "Subscriptions_create",
        "summary": "Create a subscription (send_invoice)",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSubscriptionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or a billing rule (price_inactive, customer_email_required, automatic_charging_unavailable…).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "get": {
        "operationId": "Subscriptions_list",
        "summary": "List subscriptions (newest first, cursor pagination)",
        "parameters": [
          {
            "name": "customer",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "price",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "trialing",
                "active",
                "past_due",
                "canceled"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or a billing rule (price_inactive, customer_email_required, automatic_charging_unavailable…).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/subscriptions/{id}": {
      "get": {
        "operationId": "Subscriptions_retrieve",
        "summary": "Retrieve a subscription",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or a billing rule (price_inactive, customer_email_required, automatic_charging_unavailable…).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "post": {
        "operationId": "Subscriptions_update",
        "summary": "Update a subscription (applies from the next invoice)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSubscriptionDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or a billing rule (price_inactive, customer_email_required, automatic_charging_unavailable…).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "Subscriptions_cancel",
        "summary": "Cancel a subscription now (voids its open invoices)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or a billing rule (price_inactive, customer_email_required, automatic_charging_unavailable…).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/invoices": {
      "get": {
        "operationId": "Invoices_list",
        "summary": "List invoices (newest first, cursor pagination)",
        "parameters": [
          {
            "name": "customer",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "subscription",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "open",
                "paid",
                "void",
                "uncollectible"
              ],
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or invoice_not_open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/invoices/{id}": {
      "get": {
        "operationId": "Invoices_retrieve",
        "summary": "Retrieve an invoice",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or invoice_not_open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/invoices/{id}/void": {
      "post": {
        "operationId": "Invoices_void",
        "summary": "Void an open invoice",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or invoice_not_open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/invoices/{id}/mark-uncollectible": {
      "post": {
        "operationId": "Invoices_markUncollectible",
        "summary": "Mark an open invoice uncollectible (it stays payable)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or invoice_not_open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/invoices/{id}/pay": {
      "post": {
        "operationId": "Invoices_pay",
        "summary": "Mark an open invoice paid out of band (no payment, no balance change)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PayInvoiceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure or invoice_not_open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/setup-sessions": {
      "post": {
        "operationId": "SetupSessions_create",
        "summary": "Create a domiciliación setup link for a customer (expires in 24 h)",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. Same key + same body within 24h replays the stored response (`Idempotent-Replayed: true`); a different body returns 409 `idempotency_key_reused`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSetupSessionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupSessionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure, method_not_allowed or automatic_charging_unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Setup sessions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/setup-sessions/{id}": {
      "get": {
        "operationId": "SetupSessions_retrieve",
        "summary": "Retrieve a setup session (without its url)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupSessionResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation failure, method_not_allowed or automatic_charging_unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Setup sessions"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/payment-methods/{id}": {
      "get": {
        "operationId": "PaymentMethods_retrieve",
        "summary": "Retrieve a domiciliación payment method",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payment methods"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      },
      "delete": {
        "operationId": "PaymentMethods_detach",
        "summary": "Detach a payment method; it is never charged again",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payment methods"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    },
    "/v1/customers/{id}/payment-methods": {
      "get": {
        "operationId": "PaymentMethods_list",
        "summary": "List a customer's attached payment methods (newest first)",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodListResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "Live mode not activated (`live_mode_not_activated`): the live account is pending VEX Pay review or suspended. Test keys are unaffected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "5XX": {
            "description": "Server or upstream bank error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "tags": [
          "Payment methods"
        ],
        "security": [
          {
            "tenant-api-key": []
          }
        ]
      }
    }
  },
  "info": {
    "title": "VEXPay Tenant API",
    "description": "Tenant-facing API for collecting Venezuelan payments (C2P, VPOS, Pago Móvil, débito inmediato), merchant verification, payouts, and signed webhooks.\n\n## Authentication\nSend `x-api-key: <tenant key>` on every request. Keep the key server-side and rotate it if exposed.\n\n## Going live\nNew accounts start in test mode. Live keys return 403 `live_mode_not_activated` until VEX Pay reviews your integration and activates live mode — request review from the portal once your test payments and webhooks work.\n\n## Interactive reference\nThis OpenAPI document powers Scalar at `/reference` (API) and `/api-reference` (docs portal). Download the raw contract at `/openapi.json`.\n\n## C2P flow\nCreate an intent with `POST /v1/payments/c2p/request` (on some banks VEXPay also asks the payer bank to SMS the OTP — see `otpRequested`), collect the token from your customer, then execute with `POST /v1/payments/c2p`. VEXPay does not message the customer — the payer bank sends the OTP.\n\n## externalRef\nAlways client-supplied (max 64, unique per tenant where required). On **payments** it is optional correlation for lookup — **not** an idempotency key — so reusing it can create duplicate payments, except that C2P, VPOS and débito refuse a new charge whose externalRef already has a COMPLETED payment (409 `external_ref_already_paid`, with `paymentId`). On **merchants** and **payouts** it is required and acts as the idempotency key (same payload → 200 replay; conflicting payload → 409 `external_ref_conflict`).\n\n## Idempotency-Key\nEvery mutating `POST /v1/*` accepts an optional `Idempotency-Key` header (1–255 printable ASCII). Retrying with the same key and identical body within 24h replays the original status and body (`Idempotent-Replayed: true`) instead of executing again; reusing the key with a different body returns 409 `idempotency_key_reused`, and a retry while the first request is still running returns 409 `idempotency_request_in_progress`. 5xx and 429 outcomes are not stored, so the same key can be retried. Keys are scoped per tenant (live and test never collide).\n\n## Tags\n- **Banks** — listed bank catalog with logos\n- **Payments** — quote, C2P, VPOS, Pago Móvil verify, lookups, reverse\n- **Advanced payments** — débito OTP/execute, credits, disbursements, account dispersion, change (enabled per account)\n- **Merchants** — register, verify micro-deposits, manage payout methods\n- **Products** — no-code products and payment links for the hosted checkout\n- **Checkout Sessions** — server-created single-purchase checkouts (hosted URL or embedded with @vexpay/js)\n- **Payouts** — single and batch VES payouts to verified merchants\n- **Crypto** — USDT deposit addresses, balance, networks and USDT payouts\n- **Conversions** — convert your VES balance to USDT at the market rate plus your spread (enabled per account)\n- **COP** — collect Colombian pesos with Bre-B, Nequi and Daviplata; COP balance (enabled per account)\n- **Webhooks** — endpoint CRUD + test notification",
    "version": "1.0",
    "contact": {}
  },
  "tags": [
    {
      "name": "Banks",
      "description": "Listed Venezuelan bank catalog (SIMF codes, services, logos)."
    },
    {
      "name": "Payments",
      "description": "Quotes, C2P, VPOS, Pago Móvil verification, payment lookups, and C2P reverse."
    },
    {
      "name": "Advanced payments",
      "description": "Débitos, créditos, disbursements, account payouts, and change. Returns 503 when advanced payments are unavailable in this environment."
    },
    {
      "name": "Merchants",
      "description": "Merchant registration, payout methods, and micro-deposit verification."
    },
    {
      "name": "Products",
      "description": "No-code products and shareable payment links for the hosted checkout (/pay/:slug)."
    },
    {
      "name": "Checkout Sessions",
      "description": "Single-purchase checkouts created server-side; hosted URL or embedded with @vexpay/js via a client secret."
    },
    {
      "name": "Payouts",
      "description": "Exact-VES merchant payouts with item-level idempotency."
    },
    {
      "name": "Crypto",
      "description": "USDT: per-customer deposit addresses, USDT balance, network fees, and payouts to external addresses. USDT settles in USDT (never converted to VES)."
    },
    {
      "name": "Conversions",
      "description": "Convert available VES into your USDT balance: quote (60 s), accept, track. Enabled per account; test mode completes instantly."
    },
    {
      "name": "COP",
      "description": "Colombian pesos: Bre-B (QR / transfer key), Nequi (push) and Daviplata (SMS code) payments, full refunds within 96 h, and your COP balance. COP settles in COP (never converted)."
    },
    {
      "name": "Webhooks",
      "description": "Signed webhook endpoints and test delivery."
    }
  ],
  "servers": [
    {
      "url": "/",
      "description": "Current environment"
    }
  ],
  "components": {
    "securitySchemes": {
      "tenant-api-key": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Tenant API key. Keep it server-side and rotate it if exposed."
      }
    },
    "schemas": {
      "ApiErrorDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "example": 400,
            "description": "HTTP status code mirrored in the JSON body (Nest default error shape). Absent on domain errors."
          },
          "message": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Human-readable error detail, or a validation error array.",
            "example": "usdAmount must be a positive number"
          },
          "error": {
            "type": "string",
            "example": "insufficient_balance",
            "description": "Machine-readable error code (e.g. `external_ref_conflict`, `insufficient_balance`, `idempotency_key_reused`, `live_mode_not_activated`) or, for Nest default errors, a short label such as `Bad Request`. Domain errors may include extra route-specific fields."
          }
        }
      },
      "PlatformBalanceDto": {
        "type": "object",
        "properties": {
          "tenantId": {
            "type": "string",
            "format": "uuid"
          },
          "platformId": {
            "type": "string",
            "example": "plt_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "collectedVes": {
            "type": "string",
            "example": "10000.00"
          },
          "feesVes": {
            "type": "string",
            "example": "250.00"
          },
          "paidOutVes": {
            "type": "string",
            "example": "1000.00"
          },
          "convertedVes": {
            "type": "string",
            "example": "0.00",
            "description": "Net VES spent on VES→USDT conversions."
          },
          "chargebackFeesVes": {
            "type": "string",
            "example": "0.00",
            "description": "Net card chargeback fees charged (fees minus fees returned on won disputes)."
          },
          "reserveVes": {
            "type": "string",
            "example": "100.00"
          },
          "ledgerNetVes": {
            "type": "string",
            "example": "8650.00"
          },
          "heldVes": {
            "type": "string",
            "example": "4500.00",
            "description": "VES under the 24h balance hold: incoming credits count in `ledgerNetVes` but cannot be paid out until their hold ends. Conversions and seller transfers may still use them."
          },
          "nextReleaseAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2026-10-20T00:48:52.784Z",
            "description": "When the soonest held amount becomes available; null when nothing is held."
          },
          "availableVes": {
            "type": "string",
            "example": "4150.00",
            "description": "What payouts can spend: ledgerNetVes − reserveVes − heldVes (seller obligations already deducted via SELLER_TRANSFER)."
          },
          "platformAvailableVes": {
            "type": "string",
            "example": "8650.00"
          },
          "sellerObligationsVes": {
            "type": "string",
            "example": "1200.00",
            "description": "Sum of seller pending + available obligations."
          },
          "sellerPendingVes": {
            "type": "string",
            "example": "400.00"
          },
          "sellerAvailableVes": {
            "type": "string",
            "example": "800.00"
          },
          "feePercent": {
            "type": "string",
            "example": "2.5000"
          },
          "feeFixedUsd": {
            "type": "string",
            "example": "0.00"
          },
          "balanceHoldHours": {
            "type": "number",
            "example": 24,
            "description": "Hours each incoming credit is held before payouts can spend it (0 = no hold). Set by VEXPay."
          }
        },
        "required": [
          "tenantId",
          "platformId",
          "collectedVes",
          "feesVes",
          "paidOutVes",
          "convertedVes",
          "chargebackFeesVes",
          "reserveVes",
          "ledgerNetVes",
          "availableVes",
          "platformAvailableVes",
          "sellerObligationsVes",
          "sellerPendingVes",
          "sellerAvailableVes",
          "feePercent",
          "feeFixedUsd"
        ]
      },
      "BalanceTransactionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable id of the movement; never changes or disappears."
          },
          "type": {
            "type": "string",
            "enum": [
              "payment",
              "fee",
              "payment_reversal",
              "fee_reversal",
              "payout",
              "payout_reversal",
              "chargeback",
              "chargeback_fee",
              "chargeback_reversal",
              "adjustment",
              "seller_transfer",
              "seller_transfer_reversal",
              "conversion",
              "conversion_reversal",
              "merchant_payout_fee"
            ],
            "example": "chargeback"
          },
          "amountVes": {
            "type": "string",
            "example": "-4000.00",
            "description": "Signed VES amount (negative = money out of your balance)."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid"
          },
          "payoutId": {
            "type": "string",
            "format": "uuid"
          },
          "chargebackId": {
            "type": "string",
            "format": "uuid",
            "description": "Present on chargeback movements."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "externalRef": {
            "type": "string",
            "example": "order-1042",
            "description": "externalRef of the linked payment or payout."
          },
          "description": {
            "type": "string",
            "example": "Card chargeback (fraud)"
          },
          "availableAt": {
            "type": "string",
            "format": "date-time",
            "description": "Part of the 24h balance hold: this movement counts in `heldVes` (not `availableVes`) until this time."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "type",
          "amountVes",
          "description",
          "createdAt"
        ]
      },
      "BalanceTransactionListDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BalanceTransactionDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as `cursor` to get the next (older) page; null on the last page."
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      },
      "CreateWebhookDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://merchant.example.com/webhooks/vexpay"
          },
          "secret": {
            "type": "string",
            "description": "Signing secret. If omitted, a random secret is generated and returned once.",
            "example": "replace-with-a-long-random-secret"
          },
          "events": {
            "type": "array",
            "example": [
              "payment.completed",
              "payment.failed"
            ],
            "items": {
              "type": "string",
              "enum": [
                "payment.pending",
                "payment.completed",
                "payment.failed",
                "payment.canceled",
                "payment.reversed",
                "payment.chargeback",
                "payment.chargeback_closed",
                "merchant.verified",
                "merchant.rejected",
                "merchant.deactivated",
                "merchant.reactivated",
                "merchant.balance.updated",
                "merchant.created",
                "merchant.activated",
                "merchant.updated",
                "merchant.kyb_required",
                "merchant.restricted",
                "merchant.capability.updated",
                "merchant.wallet_credit",
                "payout.completed",
                "payout.failed",
                "conversion.created",
                "conversion.completed",
                "conversion.canceled",
                "onward_payout.updated",
                "tenant.status_changed",
                "tenant.api_key.created",
                "tenant.api_key.rotated",
                "tenant.api_key.revoked",
                "tenant.live_status_changed",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "customer.subscription.created",
                "customer.subscription.updated",
                "customer.subscription.deleted",
                "customer.subscription.trial_will_end",
                "customer.subscription.reactivated",
                "invoice.created",
                "invoice.upcoming",
                "invoice.paid",
                "invoice.payment_attempt",
                "invoice.payment_failed",
                "invoice.overdue",
                "invoice.voided",
                "invoice.marked_uncollectible",
                "payment_method.attached",
                "payment_method.updated",
                "payment_method.detached",
                "notification.test"
              ]
            }
          }
        },
        "required": [
          "url",
          "events"
        ]
      },
      "WebhookEndpointDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "payment.pending",
                "payment.completed",
                "payment.failed",
                "payment.canceled",
                "payment.reversed",
                "payment.chargeback",
                "payment.chargeback_closed",
                "merchant.verified",
                "merchant.rejected",
                "merchant.deactivated",
                "merchant.reactivated",
                "merchant.balance.updated",
                "merchant.created",
                "merchant.activated",
                "merchant.updated",
                "merchant.kyb_required",
                "merchant.restricted",
                "merchant.capability.updated",
                "merchant.wallet_credit",
                "payout.completed",
                "payout.failed",
                "conversion.created",
                "conversion.completed",
                "conversion.canceled",
                "onward_payout.updated",
                "tenant.status_changed",
                "tenant.api_key.created",
                "tenant.api_key.rotated",
                "tenant.api_key.revoked",
                "tenant.live_status_changed",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "customer.subscription.created",
                "customer.subscription.updated",
                "customer.subscription.deleted",
                "customer.subscription.trial_will_end",
                "customer.subscription.reactivated",
                "invoice.created",
                "invoice.upcoming",
                "invoice.paid",
                "invoice.payment_attempt",
                "invoice.payment_failed",
                "invoice.overdue",
                "invoice.voided",
                "invoice.marked_uncollectible",
                "payment_method.attached",
                "payment_method.updated",
                "payment_method.detached",
                "notification.test"
              ]
            }
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "Returned only when the endpoint is created. Store it securely; list responses omit it."
          }
        },
        "required": [
          "id",
          "tenantId",
          "url",
          "events",
          "isActive",
          "createdAt"
        ]
      },
      "UpdateWebhookDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://merchant.example.com/webhooks/vexpay"
          },
          "events": {
            "type": "array",
            "example": [
              "payment.completed",
              "payment.failed",
              "payout.completed"
            ],
            "description": "Replaces the full event subscription list when provided.",
            "items": {
              "type": "string",
              "enum": [
                "payment.pending",
                "payment.completed",
                "payment.failed",
                "payment.canceled",
                "payment.reversed",
                "payment.chargeback",
                "payment.chargeback_closed",
                "merchant.verified",
                "merchant.rejected",
                "merchant.deactivated",
                "merchant.reactivated",
                "merchant.balance.updated",
                "merchant.created",
                "merchant.activated",
                "merchant.updated",
                "merchant.kyb_required",
                "merchant.restricted",
                "merchant.capability.updated",
                "merchant.wallet_credit",
                "payout.completed",
                "payout.failed",
                "conversion.created",
                "conversion.completed",
                "conversion.canceled",
                "onward_payout.updated",
                "tenant.status_changed",
                "tenant.api_key.created",
                "tenant.api_key.rotated",
                "tenant.api_key.revoked",
                "tenant.live_status_changed",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "customer.subscription.created",
                "customer.subscription.updated",
                "customer.subscription.deleted",
                "customer.subscription.trial_will_end",
                "customer.subscription.reactivated",
                "invoice.created",
                "invoice.upcoming",
                "invoice.paid",
                "invoice.payment_attempt",
                "invoice.payment_failed",
                "invoice.overdue",
                "invoice.voided",
                "invoice.marked_uncollectible",
                "payment_method.attached",
                "payment_method.updated",
                "payment_method.detached",
                "notification.test"
              ]
            }
          },
          "isActive": {
            "type": "boolean",
            "example": true
          }
        }
      },
      "DeleteWebhookResponseDto": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "deleted"
        ]
      },
      "PayoutResponseDto": {
        "type": "object",
        "properties": {
          "payoutId": {
            "type": "string",
            "format": "uuid",
            "description": "Payout id. Empty string only on batch item failures that never created a row."
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "pending",
              "failed",
              "awaiting_approval"
            ],
            "description": "`pending` means the credit is still reconciling (AC00); subscribe to payout webhooks or poll GET /v1/payouts/:id. `awaiting_approval` means the funds are reserved but the payout is held for VEX Pay review (see `holdReason`) and has not been sent; it later becomes `pending`/`completed` when approved or `failed` (`rejected_new_account_limit`, funds returned) when rejected."
          },
          "holdReason": {
            "type": "string",
            "enum": [
              "NEW_ACCOUNT_LIMIT"
            ],
            "description": "Why the payout was held for review. `NEW_ACCOUNT_LIMIT`: the tenant or merchant is new (first 30 days) and this payout would take its rolling 24h money-out above the new-account cap (default US$300 equivalent)."
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "description": "Bank reference when available."
          },
          "failureCode": {
            "type": "string",
            "nullable": true,
            "description": "Machine-readable failure when status is failed (e.g. merchant_inactive, payout_method_not_verified)."
          },
          "externalRef": {
            "type": "string",
            "description": "Tenant-supplied idempotency / lookup key."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Funding payment when this payout is a marketplace settlement leg."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "payoutMethodId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "merchantName": {
            "type": "string"
          },
          "monto": {
            "type": "string",
            "example": "1523.40",
            "description": "Net two-decimal VES amount credited at the bank."
          },
          "grossMonto": {
            "type": "string",
            "example": "100.00",
            "description": "Gross VES withdrawn from the ledger (instant tenant credits only)."
          },
          "feePercent": {
            "type": "string",
            "example": "2.5000",
            "description": "Platform fee percent applied on instant tenant credits."
          },
          "feeVes": {
            "type": "string",
            "example": "2.50",
            "description": "Platform fee in VES retained on instant tenant credits."
          },
          "concepto": {
            "type": "string"
          },
          "bankCode": {
            "type": "string",
            "example": "0134",
            "description": "Destination bank SIMF code."
          },
          "destination": {
            "type": "string",
            "description": "Masked phone destination, e.g. …5555"
          },
          "operationId": {
            "type": "string",
            "nullable": true,
            "description": "Network operation id while pending reconciliation."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "settledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "payoutId",
          "status"
        ]
      },
      "PayoutListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayoutResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as cursor on the next request when more pages exist"
          }
        },
        "required": [
          "items"
        ]
      },
      "PayoutBatchItemResultDto": {
        "type": "object",
        "properties": {
          "payoutId": {
            "type": "string",
            "format": "uuid",
            "description": "Payout id. Empty string only on batch item failures that never created a row."
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "pending",
              "failed",
              "awaiting_approval"
            ],
            "description": "`pending` means the credit is still reconciling (AC00); subscribe to payout webhooks or poll GET /v1/payouts/:id. `awaiting_approval` means the funds are reserved but the payout is held for VEX Pay review (see `holdReason`) and has not been sent; it later becomes `pending`/`completed` when approved or `failed` (`rejected_new_account_limit`, funds returned) when rejected."
          },
          "holdReason": {
            "type": "string",
            "enum": [
              "NEW_ACCOUNT_LIMIT"
            ],
            "description": "Why the payout was held for review. `NEW_ACCOUNT_LIMIT`: the tenant or merchant is new (first 30 days) and this payout would take its rolling 24h money-out above the new-account cap (default US$300 equivalent)."
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "description": "Bank reference when available."
          },
          "failureCode": {
            "type": "string",
            "nullable": true,
            "description": "Machine-readable failure when status is failed (e.g. merchant_inactive, payout_method_not_verified)."
          },
          "externalRef": {
            "type": "string",
            "description": "Echo of the item-level externalRef from the request (idempotency key).",
            "maxLength": 64
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Funding payment when this payout is a marketplace settlement leg."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "payoutMethodId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "merchantName": {
            "type": "string"
          },
          "monto": {
            "type": "string",
            "example": "1523.40",
            "description": "Net two-decimal VES amount credited at the bank."
          },
          "grossMonto": {
            "type": "string",
            "example": "100.00",
            "description": "Gross VES withdrawn from the ledger (instant tenant credits only)."
          },
          "feePercent": {
            "type": "string",
            "example": "2.5000",
            "description": "Platform fee percent applied on instant tenant credits."
          },
          "feeVes": {
            "type": "string",
            "example": "2.50",
            "description": "Platform fee in VES retained on instant tenant credits."
          },
          "concepto": {
            "type": "string"
          },
          "bankCode": {
            "type": "string",
            "example": "0134",
            "description": "Destination bank SIMF code."
          },
          "destination": {
            "type": "string",
            "description": "Masked phone destination, e.g. …5555"
          },
          "operationId": {
            "type": "string",
            "nullable": true,
            "description": "Network operation id while pending reconciliation."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "settledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "payoutId",
          "status"
        ]
      },
      "PayoutBatchResponseDto": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "format": "uuid",
            "description": "Batch id. Same payload + batch externalRef replays with 200."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Funding payment when this batch settles a marketplace collection."
          },
          "items": {
            "description": "Per-item results in request order. Failed items include status `failed` and failureCode; they do not abort the rest of the batch.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayoutBatchItemResultDto"
            }
          }
        },
        "required": [
          "batchId",
          "items"
        ]
      },
      "CreatePayoutDto": {
        "type": "object",
        "properties": {
          "merchantId": {
            "type": "string",
            "format": "uuid",
            "description": "Verified, active merchant that receives the payout."
          },
          "payoutMethodId": {
            "type": "string",
            "format": "uuid",
            "description": "Payout method to credit. Defaults to the merchant’s default verified method when omitted."
          },
          "monto": {
            "type": "string",
            "example": "1523.40",
            "description": "Exact two-decimal VES amount as a string. The gateway never converts FX for payouts."
          },
          "concepto": {
            "type": "string",
            "maxLength": 30,
            "example": "Liquidacion semana 30",
            "description": "Statement concept (max 30 chars)."
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "po_9c21…",
            "description": "Required idempotency key per tenant. Same payload → 200 replay; conflicting payload → 409 external_ref_conflict."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional funding payment for marketplace settlement. When set, montos are capped by remaining net (vesAmount − feeVes − PENDING/COMPLETED payouts). Multiple payouts allowed until remaining is 0."
          },
          "fromMerchantBalance": {
            "type": "boolean",
            "description": "When true, debit the seller available balance (tenant float already reserved via SELLER_TRANSFER). Default false = classic tenant-float payout."
          }
        },
        "required": [
          "merchantId",
          "monto",
          "concepto",
          "externalRef"
        ]
      },
      "CreateInstantPayoutDto": {
        "type": "object",
        "properties": {
          "monto": {
            "type": "string",
            "example": "100.00",
            "description": "Gross two-decimal VES amount to withdraw from the tenant ledger. Credits the tenant’s verified payout account (net of feePercent). Requires a verified eligible account (cooling only after destination change)."
          },
          "concepto": {
            "type": "string",
            "maxLength": 30,
            "example": "Retiro tenant",
            "description": "Statement concept (max 30 chars)."
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "ti_9c21…",
            "description": "Required idempotency key per tenant. Same payload → 200 replay; conflicting payload → 409 external_ref_conflict."
          }
        },
        "required": [
          "monto",
          "concepto",
          "externalRef"
        ]
      },
      "BatchPayoutItemDto": {
        "type": "object",
        "properties": {
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "payoutMethodId": {
            "type": "string",
            "format": "uuid",
            "description": "Payout method to credit. Defaults to the merchant’s default verified method when omitted."
          },
          "monto": {
            "type": "string",
            "example": "1523.40"
          },
          "concepto": {
            "type": "string",
            "maxLength": 30
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64
          },
          "fromMerchantBalance": {
            "type": "boolean",
            "description": "When true, debit the seller available balance instead of tenant float."
          }
        },
        "required": [
          "merchantId",
          "monto",
          "concepto",
          "externalRef"
        ]
      },
      "CreatePayoutBatchDto": {
        "type": "object",
        "properties": {
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "corte_2026-07-28",
            "description": "Batch-level idempotency key. Same externalRef + identical items → 200 replay; conflict → 409."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional funding payment for marketplace settlement. Applied to every item. Sum of item montos must fit remaining net for that payment."
          },
          "items": {
            "description": "One or more payout legs. Each item has its own externalRef (also idempotent). Failed items do not roll back successful siblings.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchPayoutItemDto"
            }
          }
        },
        "required": [
          "externalRef",
          "items"
        ]
      },
      "TenantPayoutAccountResponseDto": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "bankCode": {
            "type": "string",
            "example": "0163"
          },
          "destination": {
            "type": "string",
            "description": "Masked phone, e.g. …5555"
          },
          "identification": {
            "type": "string",
            "example": "V12345678"
          },
          "eligibility": {
            "type": "string",
            "enum": [
              "pending_verification",
              "verifying",
              "cooling",
              "eligible",
              "rejected",
              "locked"
            ],
            "description": "UI/API eligibility state. `cooling` = verified after a destination change, still within the 1 business-day wait. `eligible` = may receive instant credits (first verify unlocks immediately)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_verification",
              "verifying",
              "verified",
              "rejected"
            ]
          },
          "verifiedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "payoutEligibleAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Instant payouts allowed at/after this timestamp (verifiedAt + 1 business day)."
          },
          "failureCode": {
            "type": "string",
            "nullable": true
          },
          "lockedUntil": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "verifyExpiresAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "When the current micro-deposit confirm window expires."
          }
        },
        "required": [
          "accountId",
          "bankCode",
          "destination",
          "identification",
          "eligibility",
          "status"
        ]
      },
      "TenantPayoutAccountVerifyStartResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "verifying"
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "status",
          "expiresAt",
          "accountId"
        ]
      },
      "TenantPayoutAccountVerifyConfirmResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "eligible",
              "cooling"
            ],
            "description": "`eligible` on first successful verify (instant credits allowed immediately). `cooling` after a destination change re-verify (1 business day)."
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "payoutEligibleAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "status",
          "accountId",
          "payoutEligibleAt"
        ]
      },
      "UpsertTenantPayoutAccountDto": {
        "type": "object",
        "properties": {
          "banco": {
            "type": "string",
            "example": "0163",
            "description": "Beneficiary bank SIMF code (3–4 digits). Prefer codes from GET /v1/banks."
          },
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Beneficiary cédula/RIF."
          },
          "telefono": {
            "type": "string",
            "example": "584121234567",
            "description": "Beneficiary Pago Móvil phone (58… or 0…)."
          }
        },
        "required": [
          "banco",
          "cedula",
          "telefono"
        ]
      },
      "ConfirmTenantPayoutAccountVerifyDto": {
        "type": "object",
        "properties": {
          "amount1": {
            "type": "string",
            "example": "0.37",
            "description": "First micro-deposit amount (exact two decimals)."
          },
          "amount2": {
            "type": "string",
            "example": "0.12",
            "description": "Second micro-deposit amount (exact two decimals)."
          }
        },
        "required": [
          "amount1",
          "amount2"
        ]
      },
      "DebitOtpResponseDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "202",
            "description": "Typically `202` when the payer bank accepted the OTP request and will SMS the customer."
          },
          "message": {
            "type": "string",
            "example": "Operación aceptada",
            "description": "Human-readable network message when provided."
          },
          "reference": {
            "type": "string",
            "example": "16142940",
            "description": "Bank reference when the operation settles synchronously."
          },
          "id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Network operation id. Prefer this over `Id` when both are present. Use with GET /v1/payments/operations/:id."
          },
          "Id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Alternate casing of the operation id some network responses use."
          },
          "success": {
            "type": "boolean",
            "example": true,
            "description": "Present on some operation responses when the network returns an explicit success flag."
          }
        },
        "required": [
          "code"
        ]
      },
      "ImmediateDebitResponseDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "ACCP",
            "description": "Network status code. Common values: `202` (OTP accepted), `ACCP` (accepted/completed), `AC00` (pending — gateway auto-polls), reject codes on failure."
          },
          "message": {
            "type": "string",
            "example": "Operación aceptada",
            "description": "Human-readable network message when provided."
          },
          "reference": {
            "type": "string",
            "example": "16142940",
            "description": "Bank reference when the operation settles synchronously."
          },
          "id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Network operation id. Prefer this over `Id` when both are present. Use with GET /v1/payments/operations/:id."
          },
          "Id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Alternate casing of the operation id some network responses use."
          },
          "success": {
            "type": "boolean",
            "example": true,
            "description": "Present on some operation responses when the network returns an explicit success flag."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "example": "3fd84b2d-9ad1-4f74-a2d9-0f2f56984db5",
            "description": "VEXPay payment id for this débito inmediato (method DEBITO_INMEDIATO)."
          },
          "externalRef": {
            "type": "string",
            "example": "fine_736a0b42-0b6e-454c-b87e-7f3c0e47057b",
            "description": "Echo of the request externalRef when provided."
          }
        },
        "required": [
          "code",
          "paymentId"
        ]
      },
      "R4OperationResponseDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "ACCP",
            "description": "Network status code. Common values: `202` (OTP accepted), `ACCP` (accepted/completed), `AC00` (pending — gateway auto-polls), reject codes on failure."
          },
          "message": {
            "type": "string",
            "example": "Operación aceptada",
            "description": "Human-readable network message when provided."
          },
          "reference": {
            "type": "string",
            "example": "16142940",
            "description": "Bank reference when the operation settles synchronously."
          },
          "id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Network operation id. Prefer this over `Id` when both are present. Use with GET /v1/payments/operations/:id."
          },
          "Id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Alternate casing of the operation id some network responses use."
          },
          "success": {
            "type": "boolean",
            "example": true,
            "description": "Present on some operation responses when the network returns an explicit success flag."
          }
        },
        "required": [
          "code"
        ]
      },
      "CreditDisbursementResponseDto": {
        "type": "object",
        "properties": {
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "description": "Id of the completed PAGO_MOVIL payment that funded this disbursement."
          },
          "referencia": {
            "type": "string",
            "example": "12345678",
            "description": "Normalized bank reference used to locate the inbound payment."
          },
          "credits": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "telefono": {
                  "type": "string",
                  "example": "584121234567"
                },
                "code": {
                  "type": "string",
                  "example": "ACCP"
                },
                "reference": {
                  "type": "string",
                  "example": "16142940"
                },
                "id": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "required": [
                "telefono",
                "code"
              ]
            },
            "description": "Per-recipient credit results in request order."
          }
        },
        "required": [
          "paymentId",
          "referencia",
          "credits"
        ]
      },
      "AccountPayoutDispersionResponseDto": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true,
            "description": "Whether the bank network accepted the dispersion request."
          },
          "message": {
            "type": "string",
            "description": "Network success message when provided."
          },
          "error": {
            "type": "string",
            "description": "Network error detail when success is false."
          },
          "referencia": {
            "type": "string",
            "example": "123456789",
            "description": "9-digit wire reference actually sent to the bank (last 9 digits of the request referencia)."
          }
        },
        "required": [
          "success",
          "referencia"
        ]
      },
      "ChangePaymentResponseDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "ACCP",
            "description": "Network status code. Common values: `202` (OTP accepted), `ACCP` (accepted/completed), `AC00` (pending — gateway auto-polls), reject codes on failure."
          },
          "message": {
            "type": "string",
            "example": "Operación aceptada",
            "description": "Human-readable network message when provided."
          },
          "reference": {
            "type": "string",
            "example": "16142940",
            "description": "Bank reference when the operation settles synchronously."
          },
          "id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Network operation id. Prefer this over `Id` when both are present. Use with GET /v1/payments/operations/:id."
          },
          "Id": {
            "type": "string",
            "example": "6785d97e-2092-49f0-9f7d-3d5921f0b13f",
            "description": "Alternate casing of the operation id some network responses use."
          },
          "success": {
            "type": "boolean",
            "example": true,
            "description": "Present on some operation responses when the network returns an explicit success flag."
          }
        },
        "required": [
          "code"
        ]
      },
      "ManualOperationPollResponseDto": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "debit",
              "payout",
              "verification_deposit"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "operationId": {
            "type": "string",
            "description": "Network operation id that was polled."
          },
          "statusBefore": {
            "type": "string",
            "example": "PENDING"
          },
          "status": {
            "type": "string",
            "example": "COMPLETED"
          },
          "failureCode": {
            "type": "string",
            "nullable": true
          },
          "code": {
            "type": "string",
            "nullable": true,
            "example": "AC00",
            "description": "Latest network code from ConsultarOperaciones when available."
          },
          "message": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          }
        },
        "required": [
          "kind",
          "id",
          "operationId",
          "statusBefore",
          "status"
        ]
      },
      "GenerateDebitOtpDto": {
        "type": "object",
        "properties": {
          "banco": {
            "type": "string",
            "example": "0191",
            "pattern": "^\\d{3,4}$",
            "description": "3–4 digit bank code (padded to 4 digits when sent to the network). Prefer codes from GET /v1/banks."
          },
          "monto": {
            "type": "number",
            "example": 50,
            "minimum": 0.01,
            "maximum": 1000000,
            "description": "Debit amount in VES (not USD)."
          },
          "telefono": {
            "type": "string",
            "example": "584121234567",
            "description": "Payer mobile: 58 + 10 digits, or 0 + 10 digits local form."
          },
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Payer cédula/RIF (V/E/J/P/G + digits)."
          }
        },
        "required": [
          "banco",
          "monto",
          "telefono",
          "cedula"
        ]
      },
      "ImmediateDebitDto": {
        "type": "object",
        "properties": {
          "banco": {
            "type": "string",
            "example": "0191",
            "pattern": "^\\d{3,4}$",
            "description": "3–4 digit bank code (padded to 4 digits when sent to the network). Prefer codes from GET /v1/banks."
          },
          "monto": {
            "type": "number",
            "example": 50,
            "minimum": 0.01,
            "maximum": 1000000,
            "description": "Debit amount in VES (not USD)."
          },
          "telefono": {
            "type": "string",
            "example": "584121234567",
            "description": "Payer mobile: 58 + 10 digits, or 0 + 10 digits local form."
          },
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Payer cédula/RIF (V/E/J/P/G + digits)."
          },
          "nombre": {
            "type": "string",
            "example": "Maria Perez",
            "maxLength": 20,
            "description": "Payer display name (max 20 chars, truncated for the bank)."
          },
          "otp": {
            "type": "string",
            "example": "123456",
            "pattern": "^\\d{6,8}$",
            "description": "OTP the payer bank SMS’d after POST /v1/payments/debit/otp."
          },
          "concepto": {
            "type": "string",
            "example": "Pago de factura",
            "maxLength": 30,
            "description": "Statement concept shown to the payer (max 30 chars)."
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "fine_736a0b42-0b6e-454c-b87e-7f3c0e47057b",
            "description": "Tenant correlation value for recovery lookup (GET /v1/payments/by-ref/:externalRef). Not an idempotency key; a ref that already has a COMPLETED payment is refused (409 external_ref_already_paid)."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "applicationFeeVes": {
            "type": "string",
            "example": "50.00",
            "description": "Marketplace application fee in VES retained by the platform."
          },
          "applicationFeePercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "example": 10,
            "description": "Optional percent of vesAmount used when applicationFeeVes is omitted. When both are omitted and merchantId is set, the merchant's commission (or the tenant default commission) applies."
          }
        },
        "required": [
          "banco",
          "monto",
          "telefono",
          "cedula",
          "nombre",
          "otp",
          "concepto"
        ]
      },
      "ManualOperationPollDto": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "debit",
              "payout",
              "verification_deposit"
            ],
            "example": "debit",
            "description": "Which pending entity to reconcile."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "3fd84b2d-9ad1-4f74-a2d9-0f2f56984db5",
            "description": "Payment, payout, or verification deposit id (not the network operation id)."
          }
        },
        "required": [
          "kind",
          "id"
        ]
      },
      "ImmediateCreditDto": {
        "type": "object",
        "properties": {
          "banco": {
            "type": "string",
            "example": "0191",
            "description": "Beneficiary bank code (3–4 digits). Prefer codes from GET /v1/banks."
          },
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Beneficiary cédula/RIF."
          },
          "telefono": {
            "type": "string",
            "example": "584121234567",
            "description": "Beneficiary Pago Móvil phone (58… or 0…)."
          },
          "monto": {
            "type": "number",
            "example": 50,
            "minimum": 0.01,
            "maximum": 1000000,
            "description": "Credit amount in VES."
          },
          "concepto": {
            "type": "string",
            "example": "Pago de factura",
            "maxLength": 30,
            "description": "Statement concept (max 30 chars)."
          }
        },
        "required": [
          "banco",
          "cedula",
          "telefono",
          "monto",
          "concepto"
        ]
      },
      "AccountCreditDto": {
        "type": "object",
        "properties": {
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Account holder cédula/RIF."
          },
          "cuenta": {
            "type": "string",
            "example": "01910000000000000000",
            "minLength": 20,
            "maxLength": 20,
            "description": "20-digit Venezuelan bank account number."
          },
          "monto": {
            "type": "number",
            "example": 50,
            "description": "Credit amount in VES."
          },
          "concepto": {
            "type": "string",
            "example": "Pago de factura",
            "maxLength": 30,
            "description": "Statement concept (max 30 chars)."
          }
        },
        "required": [
          "cedula",
          "cuenta",
          "monto",
          "concepto"
        ]
      },
      "CreditRecipientDto": {
        "type": "object",
        "properties": {
          "banco": {
            "type": "string",
            "example": "0191",
            "description": "Recipient bank code (3–4 digits)."
          },
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Recipient cédula/RIF."
          },
          "telefono": {
            "type": "string",
            "example": "584121234567",
            "description": "Recipient Pago Móvil phone."
          },
          "montoPart": {
            "type": "number",
            "example": 25,
            "description": "Share of the total disbursement for this recipient (VES). Sum of montoPart must equal monto."
          }
        },
        "required": [
          "banco",
          "cedula",
          "telefono",
          "montoPart"
        ]
      },
      "CreditDisbursementDto": {
        "type": "object",
        "properties": {
          "monto": {
            "type": "number",
            "example": 50,
            "description": "Total VES amount to disburse. Must match a completed PAGO_MOVIL payment’s vesAmount for the given referencia."
          },
          "referencia": {
            "type": "string",
            "example": "123456789",
            "description": "Bank reference of a completed inbound Pago Móvil payment (up to 9 digits). Used to locate and mark that payment as dispersed."
          },
          "concepto": {
            "type": "string",
            "example": "Dispersión",
            "maxLength": 30,
            "description": "Concept applied to each credit leg."
          },
          "personas": {
            "description": "One or more phone recipients. Sum of personas[].montoPart must equal monto.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditRecipientDto"
            }
          }
        },
        "required": [
          "monto",
          "referencia",
          "concepto",
          "personas"
        ]
      },
      "PayoutRecipientDto": {
        "type": "object",
        "properties": {
          "nombres": {
            "type": "string",
            "example": "Maria Perez",
            "maxLength": 80,
            "description": "Beneficiary legal name."
          },
          "documento": {
            "type": "string",
            "example": "V12345678",
            "description": "Beneficiary documento (V/E/J/P + digits)."
          },
          "destino": {
            "type": "string",
            "example": "01910000000000000000",
            "minLength": 20,
            "maxLength": 20,
            "description": "20-digit destination account number."
          },
          "montoPart": {
            "type": "number",
            "example": 25,
            "description": "Share for this beneficiary (VES). Sum of montoPart must equal monto."
          }
        },
        "required": [
          "nombres",
          "documento",
          "destino",
          "montoPart"
        ]
      },
      "PayoutDto": {
        "type": "object",
        "properties": {
          "monto": {
            "type": "number",
            "example": 50,
            "description": "Total VES amount across all personas."
          },
          "fecha": {
            "type": "string",
            "example": "07/20/2026",
            "pattern": "^\\d{2}/\\d{2}/\\d{4}$",
            "description": "Value date as MM/DD/YYYY."
          },
          "referencia": {
            "type": "string",
            "example": "123456789",
            "description": "Numeric reference (digits only). Only the last 9 digits are sent to the bank network."
          },
          "personas": {
            "description": "Account beneficiaries. Sum of personas[].montoPart must equal monto.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayoutRecipientDto"
            }
          }
        },
        "required": [
          "monto",
          "fecha",
          "referencia",
          "personas"
        ]
      },
      "ChangePaymentDto": {
        "type": "object",
        "properties": {
          "telefonoDestino": {
            "type": "string",
            "example": "584121234567",
            "description": "Customer phone that receives the change (vuelto)."
          },
          "cedula": {
            "type": "string",
            "example": "V12345678",
            "description": "Customer cédula/RIF."
          },
          "banco": {
            "type": "string",
            "example": "0191",
            "description": "Customer bank code (3–4 digits)."
          },
          "monto": {
            "type": "number",
            "example": 5,
            "description": "Change amount in VES."
          },
          "concepto": {
            "type": "string",
            "example": "Vuelto de compra",
            "maxLength": 30,
            "description": "Optional statement concept (max 30 chars)."
          },
          "ip": {
            "type": "string",
            "example": "203.0.113.10",
            "maxLength": 15,
            "description": "Client IP recorded with the operation. Defaults to R4_DEFAULT_CLIENT_IP when omitted."
          }
        },
        "required": [
          "telefonoDestino",
          "cedula",
          "banco",
          "monto"
        ]
      },
      "CryptoBalanceDto": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "example": "USDT",
            "enum": [
              "USDT",
              "USDC"
            ]
          },
          "available": {
            "type": "string",
            "example": "97.00",
            "description": "Available for payouts, in `currency` (ledger). Excludes `held`."
          },
          "held": {
            "type": "string",
            "example": "0.00",
            "description": "Under the 24h balance hold: credited but not payable until its hold ends, in `currency`."
          },
          "nextReleaseAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the soonest held amount becomes available; null when nothing is held."
          },
          "pendingPayout": {
            "type": "string",
            "example": "50.10",
            "description": "Reserved by payouts that have not completed yet, in `currency`."
          },
          "availableUsdt": {
            "type": "string",
            "example": "97.00",
            "description": "USDT only: same as `available`."
          },
          "pendingPayoutUsdt": {
            "type": "string",
            "example": "50.10",
            "description": "USDT only: same as `pendingPayout`."
          },
          "heldUsdt": {
            "type": "string",
            "example": "0.00",
            "description": "USDT only: same as `held`."
          },
          "asOf": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "currency",
          "available",
          "pendingPayout",
          "asOf"
        ]
      },
      "CryptoBalancesDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "One balance per stablecoin (USDT, USDC).",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CryptoBalanceDto"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "CreateDepositAddressDto": {
        "type": "object",
        "properties": {
          "customerRef": {
            "type": "string",
            "example": "user_123",
            "description": "Your identifier for the customer this address belongs to (1–128 chars: A–Z a–z 0–9 _ . : @ -)."
          },
          "network": {
            "type": "string",
            "example": "BEP20",
            "enum": [
              "TRC20",
              "BEP20",
              "POLYGON",
              "SOL",
              "TON",
              "ARB1",
              "BASE"
            ],
            "description": "USDT: TRC20, BEP20, POLYGON, SOL, TON, ARB1. USDC: POLYGON, BASE."
          },
          "currency": {
            "type": "string",
            "example": "USDT",
            "enum": [
              "USDT",
              "USDC"
            ],
            "default": "USDT",
            "description": "Stablecoin the address receives."
          }
        },
        "required": [
          "customerRef",
          "network"
        ]
      },
      "DepositAddressDto": {
        "type": "object",
        "properties": {
          "customerRef": {
            "type": "string",
            "example": "user_123"
          },
          "network": {
            "type": "string",
            "example": "BEP20"
          },
          "currency": {
            "type": "string",
            "example": "USDT",
            "enum": [
              "USDT",
              "USDC"
            ]
          },
          "address": {
            "type": "string",
            "example": "0x9f3c…"
          },
          "tag": {
            "type": "string",
            "description": "Destination tag / memo the payer must include (TON)."
          },
          "tagRequired": {
            "type": "boolean",
            "description": "True when the network requires the tag."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "customerRef",
          "network",
          "currency",
          "address",
          "tagRequired",
          "createdAt"
        ]
      },
      "CryptoNetworkDto": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "example": "USDT",
            "enum": [
              "USDT",
              "USDC"
            ]
          },
          "network": {
            "type": "string",
            "example": "POLYGON"
          },
          "displayName": {
            "type": "string",
            "example": "Polygon"
          },
          "receiveEnabled": {
            "type": "boolean"
          },
          "payoutEnabled": {
            "type": "boolean"
          },
          "payoutFee": {
            "type": "string",
            "example": "0.10",
            "description": "Payout fee in `currency`."
          },
          "minPayout": {
            "type": "string",
            "example": "1.00",
            "description": "Minimum payout in `currency`."
          },
          "payoutFeeUsdt": {
            "type": "string",
            "example": "0.10",
            "description": "USDT only: same as `payoutFee`."
          },
          "minPayoutUsdt": {
            "type": "string",
            "example": "1.00",
            "description": "USDT only: same as `minPayout`."
          },
          "tagRequired": {
            "type": "boolean"
          },
          "available": {
            "type": "boolean",
            "description": "Whether a payout of the requested amount can be sent on this network now."
          }
        },
        "required": [
          "currency",
          "network",
          "displayName",
          "receiveEnabled",
          "payoutEnabled",
          "payoutFee",
          "minPayout",
          "tagRequired",
          "available"
        ]
      },
      "CreateCryptoPayoutDto": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "example": "USDT",
            "enum": [
              "USDT",
              "USDC"
            ],
            "default": "USDT",
            "description": "Stablecoin to send; debits that balance."
          },
          "network": {
            "type": "string",
            "example": "POLYGON",
            "enum": [
              "TRC20",
              "BEP20",
              "POLYGON",
              "SOL",
              "TON",
              "ARB1",
              "BASE"
            ],
            "description": "USDT: TRC20, BEP20, POLYGON, SOL, TON, ARB1. USDC: POLYGON, BASE."
          },
          "address": {
            "type": "string",
            "example": "0x9f3c4e1b2a7d6c5e4f3a2b1c0d9e8f7a6b5c4d3e"
          },
          "tag": {
            "type": "string",
            "description": "Destination tag / memo (required on TON)."
          },
          "amount": {
            "type": "string",
            "example": "50.00",
            "description": "Amount the destination receives, in `currency` (max 2 decimals)."
          },
          "amountUsdt": {
            "type": "string",
            "example": "50.00",
            "description": "USDT only: alias of `amount`."
          },
          "customerRef": {
            "type": "string",
            "example": "user_123",
            "description": "Your customer reference, echoed on webhooks."
          },
          "idempotencyKey": {
            "type": "string",
            "example": "withdrawal_8812",
            "description": "Unique per payout. Replays return the same payout (200)."
          }
        },
        "required": [
          "network",
          "address",
          "idempotencyKey"
        ]
      },
      "CryptoPayoutDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "crypto.payout"
          },
          "currency": {
            "type": "string",
            "example": "USDT",
            "enum": [
              "USDT",
              "USDC"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ]
          },
          "network": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "tag": {
            "type": "string"
          },
          "amount": {
            "type": "string",
            "example": "50.00",
            "description": "Amount sent, in `currency`."
          },
          "fee": {
            "type": "string",
            "example": "0.10",
            "description": "Network fee + margin, in `currency` (0 for internal)."
          },
          "amountUsdt": {
            "type": "string",
            "example": "50.00",
            "description": "USDT only: same as `amount`."
          },
          "feeUsdt": {
            "type": "string",
            "example": "0.10",
            "description": "USDT only: same as `fee`."
          },
          "customerRef": {
            "type": "string"
          },
          "merchantId": {
            "type": "string"
          },
          "idempotencyKey": {
            "type": "string"
          },
          "txHash": {
            "type": "string"
          },
          "internal": {
            "type": "boolean",
            "description": "Settled inside VEXPay (destination is one of your own deposit addresses)."
          },
          "failureReason": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "object",
          "currency",
          "status",
          "network",
          "address",
          "amount",
          "fee",
          "idempotencyKey",
          "internal",
          "createdAt"
        ]
      },
      "CopChannelDto": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "string",
            "enum": [
              "breb",
              "nequi",
              "daviplata",
              "card",
              "pse",
              "bancolombia_transfer",
              "bancolombia_qr"
            ],
            "example": "pse"
          },
          "label": {
            "type": "string",
            "example": "PSE",
            "description": "Buyer-facing name (Spanish)."
          },
          "needsBuyer": {
            "type": "boolean",
            "example": true,
            "description": "A `buyer` object is required."
          },
          "needsTermsAcceptance": {
            "type": "boolean",
            "example": true,
            "description": "Show the buyer the `terms` links and send `buyer.termsAccepted: true`."
          },
          "checkoutOnly": {
            "type": "boolean",
            "example": false,
            "description": "Only through the hosted checkout (checkout sessions or payment links), never `POST /v1/cop/payments`."
          },
          "minAmountCop": {
            "type": "number",
            "example": 20000
          }
        },
        "required": [
          "channel",
          "label",
          "needsBuyer",
          "needsTermsAcceptance",
          "checkoutOnly",
          "minAmountCop"
        ]
      },
      "CopPseBankDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "1007"
          },
          "name": {
            "type": "string",
            "example": "Bancolombia"
          }
        },
        "required": [
          "code",
          "name"
        ]
      },
      "CopTermsDto": {
        "type": "object",
        "properties": {
          "termsUrl": {
            "type": "string",
            "description": "Terms and conditions the buyer accepts."
          },
          "personalDataUrl": {
            "type": "string",
            "description": "Personal data processing authorization the buyer accepts."
          }
        },
        "required": [
          "termsUrl",
          "personalDataUrl"
        ]
      },
      "CopChannelsDto": {
        "type": "object",
        "properties": {
          "channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CopChannelDto"
            }
          },
          "pseBanks": {
            "description": "Present when `pse` is listed: banks for `pse.bankCode`.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CopPseBankDto"
            }
          },
          "terms": {
            "description": "Present when a listed channel needs terms acceptance.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CopTermsDto"
              }
            ]
          }
        },
        "required": [
          "channels"
        ]
      },
      "CopBuyerDto": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string",
            "example": "Juan",
            "maxLength": 50
          },
          "lastName": {
            "type": "string",
            "example": "Pérez",
            "maxLength": 50
          },
          "email": {
            "type": "string",
            "example": "juan@example.com",
            "description": "Required for every channel except `breb`."
          },
          "phone": {
            "type": "string",
            "example": "3001234567",
            "description": "Colombian mobile number (10 digits starting with 3, with or without +57). Required for Nequi (it receives the push) and Daviplata."
          },
          "documentType": {
            "type": "string",
            "enum": [
              "CC",
              "CE",
              "TI",
              "NIT",
              "PP"
            ],
            "example": "CC",
            "description": "Required for Nequi and Daviplata. Daviplata accepts CC, CE and TI only."
          },
          "documentNumber": {
            "type": "string",
            "example": "1234567890",
            "description": "National document number. Required for every channel except `breb`."
          },
          "personType": {
            "type": "string",
            "enum": [
              "natural",
              "juridica"
            ],
            "example": "natural",
            "description": "PSE only (required): `natural` person or `juridica` (company)."
          },
          "termsAccepted": {
            "type": "boolean",
            "example": true,
            "description": "Required (`true`) for channels the channel catalog marks `needsTermsAcceptance`: confirms you showed the buyer the catalog `terms` links."
          }
        }
      },
      "CopPseDto": {
        "type": "object",
        "properties": {
          "bankCode": {
            "type": "string",
            "example": "1007",
            "description": "Bank code from `GET /v1/cop/channels` → `pseBanks`."
          }
        },
        "required": [
          "bankCode"
        ]
      },
      "CreateCopPaymentDto": {
        "type": "object",
        "properties": {
          "amountCop": {
            "type": "number",
            "example": 100000,
            "minimum": 2000,
            "description": "Amount in whole Colombian pesos. At least 2,000 (`amount_below_minimum` otherwise)."
          },
          "channel": {
            "type": "string",
            "enum": [
              "breb",
              "nequi",
              "daviplata",
              "card",
              "pse",
              "bancolombia_transfer",
              "bancolombia_qr"
            ],
            "example": "breb",
            "description": "`breb`: QR code / transfer key the buyer pays from any Colombian bank app. `nequi`: push to the buyer's Nequi app. `daviplata`: SMS code the buyer reads to you, or a redirect. `pse` and `bancolombia_transfer`: redirect to the buyer's bank. `bancolombia_qr`: QR the buyer scans in the Bancolombia app. `card`: hosted checkout only (`channel_requires_checkout`)."
          },
          "description": {
            "type": "string",
            "example": "Order 1042",
            "maxLength": 255,
            "description": "Shown to the buyer."
          },
          "reference": {
            "type": "string",
            "example": "order-1042",
            "maxLength": 64,
            "description": "Your reference, echoed in reads and webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "orderId": "1042"
            },
            "description": "Up to 20 string key/value pairs (keys ≤ 40 chars, values ≤ 500 chars)."
          },
          "buyer": {
            "description": "Required for every channel except `breb`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CopBuyerDto"
              }
            ]
          },
          "pse": {
            "description": "Required for `pse`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CopPseDto"
              }
            ]
          }
        },
        "required": [
          "amountCop",
          "channel"
        ]
      },
      "CopNextActionDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "show_qr",
              "approve_in_app",
              "submit_otp",
              "redirect",
              "redirect_pending",
              "processing"
            ],
            "description": "`redirect`: send the buyer to `url` to authorize at their bank. `redirect_pending`: the URL is not ready yet — read the payment again. `processing`: nothing to do, the outcome follows."
          },
          "qrPngBase64": {
            "type": "string",
            "description": "Bre-B: base64 PNG of the payment QR. Returned only when the payment is created."
          },
          "qrSvgBase64": {
            "type": "string",
            "description": "Bancolombia QR: base64 SVG of the payment QR."
          },
          "url": {
            "type": "string",
            "example": "https://…",
            "description": "`redirect`: where the buyer authorizes the payment."
          },
          "transferKey": {
            "type": "string",
            "description": "Bre-B: transfer key the buyer can enter instead of scanning."
          },
          "phoneMasked": {
            "type": "string",
            "example": "****567",
            "description": "Nequi: masked phone that received the push."
          }
        },
        "required": [
          "type"
        ]
      },
      "CopPaymentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed",
              "canceled",
              "refunded"
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "COP"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "breb",
              "nequi",
              "daviplata",
              "card",
              "pse",
              "bancolombia_transfer",
              "bancolombia_qr"
            ]
          },
          "amountCop": {
            "type": "number",
            "example": 100000
          },
          "feeCop": {
            "type": "number",
            "example": 3500,
            "description": "Present once completed."
          },
          "amountUsd": {
            "type": "string",
            "example": "5.00",
            "description": "Hosted checkout payments only: the USD price the peso amount was computed from."
          },
          "copRate": {
            "type": "string",
            "example": "3316.382375",
            "description": "Hosted checkout payments only: COP per USD the buyer was charged at."
          },
          "reference": {
            "type": "string",
            "example": "order-1042"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "failureCode": {
            "type": "string",
            "enum": [
              "expired",
              "rejected",
              "processor_error",
              "processor_unknown",
              "chargeback"
            ],
            "description": "`chargeback`: a refunded card payment the buyer disputed with their bank."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "next": {
            "description": "What the buyer must do next. Returned when the payment is created, and on reads while a bank redirect or QR is pending.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CopNextActionDto"
              }
            ]
          },
          "card": {
            "type": "object",
            "example": {
              "brand": "VISA",
              "last4": "4242"
            },
            "description": "Card payments: brand and last 4 digits, once known."
          }
        },
        "required": [
          "id",
          "status",
          "method",
          "channel",
          "amountCop",
          "metadata",
          "createdAt"
        ]
      },
      "SubmitCopOtpDto": {
        "type": "object",
        "properties": {
          "otp": {
            "type": "string",
            "example": "123456",
            "description": "The code the buyer received by SMS."
          }
        },
        "required": [
          "otp"
        ]
      },
      "CopBalanceDto": {
        "type": "object",
        "properties": {
          "availableCop": {
            "type": "number",
            "example": 96500,
            "description": "Whole pesos available for payout. Excludes `heldCop`."
          },
          "heldCop": {
            "type": "number",
            "example": 0,
            "description": "Whole pesos under the 24h balance hold: credited but not payable until the hold ends."
          },
          "nextReleaseAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the soonest held amount becomes available; null when nothing is held."
          },
          "pendingPayoutCop": {
            "type": "number",
            "example": 0,
            "description": "Whole pesos reserved by payouts in progress."
          },
          "asOf": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "availableCop",
          "pendingPayoutCop",
          "asOf"
        ]
      },
      "CurrencyFlagsDto": {
        "type": "object",
        "properties": {
          "VES": {
            "type": "boolean"
          },
          "COP": {
            "type": "boolean"
          }
        },
        "required": [
          "VES",
          "COP"
        ]
      },
      "CurrencyAmountsDto": {
        "type": "object",
        "properties": {
          "VES": {
            "type": "string",
            "example": "3.0000"
          },
          "COP": {
            "type": "string",
            "example": "3.0000"
          }
        },
        "required": [
          "VES",
          "COP"
        ]
      },
      "CurrencyCapsDto": {
        "type": "object",
        "properties": {
          "VES": {
            "type": "string",
            "nullable": true,
            "example": null,
            "description": "Max VES per Caracas day; `null` = no cap."
          },
          "COP": {
            "type": "string",
            "nullable": true,
            "example": "2000000",
            "description": "Max COP per Bogotá day; `null` = no cap."
          }
        },
        "required": [
          "VES",
          "COP"
        ]
      },
      "AutoConvertPercentDto": {
        "type": "object",
        "properties": {
          "percent": {
            "type": "integer",
            "example": 50,
            "minimum": 0,
            "maximum": 100,
            "description": "Whole number; 0 = off."
          }
        },
        "required": [
          "percent"
        ]
      },
      "AutoConvertDto": {
        "type": "object",
        "properties": {
          "COP": {
            "$ref": "#/components/schemas/AutoConvertPercentDto"
          }
        },
        "required": [
          "COP"
        ]
      },
      "ConversionSettingsDto": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "example": "conversion_settings"
          },
          "enabled": {
            "type": "boolean",
            "description": "Conversions are enabled for your account."
          },
          "sourceCurrencies": {
            "description": "Which currencies you can convert from right now.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CurrencyFlagsDto"
              }
            ]
          },
          "spreadPercent": {
            "description": "Your spread per source currency, in percent.",
            "allOf": [
              {
                "$ref": "#/components/schemas/CurrencyAmountsDto"
              }
            ]
          },
          "minimumUsdt": {
            "type": "string",
            "example": "10.00",
            "description": "Smallest USDT amount a conversion may deliver."
          },
          "dailyMax": {
            "$ref": "#/components/schemas/CurrencyCapsDto"
          },
          "autoConvert": {
            "$ref": "#/components/schemas/AutoConvertDto"
          }
        },
        "required": [
          "object",
          "enabled",
          "sourceCurrencies",
          "spreadPercent",
          "minimumUsdt",
          "dailyMax",
          "autoConvert"
        ]
      },
      "UpdateConversionSettingsDto": {
        "type": "object",
        "properties": {
          "autoConvert": {
            "example": {
              "COP": {
                "percent": 50
              }
            },
            "allOf": [
              {
                "$ref": "#/components/schemas/AutoConvertDto"
              }
            ]
          }
        },
        "required": [
          "autoConvert"
        ]
      },
      "CreateConversionQuoteDto": {
        "type": "object",
        "properties": {
          "sourceCurrency": {
            "type": "string",
            "enum": [
              "VES",
              "COP"
            ],
            "default": "VES",
            "description": "Currency you convert from. Defaults to `VES`."
          },
          "sourceAmount": {
            "type": "string",
            "example": "1000000",
            "description": "Amount of `sourceCurrency` to spend (VES: up to 2 decimals; COP: whole pesos). Send this or `targetAmountUsdt`, not both."
          },
          "sourceAmountVes": {
            "type": "string",
            "example": "10000.00",
            "description": "VES only: same as `sourceAmount` (kept for existing integrations)."
          },
          "targetAmountUsdt": {
            "type": "string",
            "example": "50.00",
            "description": "USDT to receive. Send this or `sourceAmount`, not both."
          }
        }
      },
      "ConversionQuoteDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "conversion_quote"
          },
          "rate": {
            "type": "string",
            "example": "998.8299",
            "description": "Units of `sourceCurrency` per 1 USDT you get: market rate plus your spread."
          },
          "marketRate": {
            "type": "string",
            "example": "979.2450",
            "description": "Market USDT rate (in `sourceCurrency`) the quote is based on."
          },
          "spreadPercent": {
            "type": "string",
            "example": "2.0000",
            "description": "Your spread, in percent."
          },
          "rateSource": {
            "type": "string",
            "example": "market",
            "enum": [
              "market"
            ]
          },
          "sourceCurrency": {
            "type": "string",
            "enum": [
              "VES",
              "COP"
            ]
          },
          "sourceAmount": {
            "type": "string",
            "example": "10000.00",
            "description": "Amount debited (VES to the cent, COP in whole pesos; rounded up)."
          },
          "sourceAmountVes": {
            "type": "string",
            "example": "10000.00",
            "nullable": true,
            "description": "VES quotes only; `null` for COP."
          },
          "targetAmountUsdt": {
            "type": "string",
            "example": "10.01",
            "description": "Rounded down to the cent."
          },
          "expiresAt": {
            "type": "string",
            "description": "The quote can be accepted until this time (60 seconds)."
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "rate",
          "marketRate",
          "spreadPercent",
          "rateSource",
          "sourceCurrency",
          "sourceAmount",
          "sourceAmountVes",
          "targetAmountUsdt",
          "expiresAt",
          "createdAt"
        ]
      },
      "CreateConversionDto": {
        "type": "object",
        "properties": {
          "quoteId": {
            "type": "string",
            "description": "A live quote from `POST /v1/conversions/quotes`. Each quote can be used once."
          },
          "reference": {
            "type": "string",
            "example": "treasury-2026-10-03",
            "description": "Your reference, echoed on the conversion and its webhooks."
          }
        },
        "required": [
          "quoteId"
        ]
      },
      "ConversionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "conversion"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "COMPLETED",
              "CANCELED"
            ]
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "rate": {
            "type": "string",
            "example": "998.8299"
          },
          "marketRate": {
            "type": "string",
            "example": "979.2450"
          },
          "spreadPercent": {
            "type": "string",
            "example": "2.0000"
          },
          "rateSource": {
            "type": "string",
            "example": "market",
            "enum": [
              "market"
            ]
          },
          "sourceCurrency": {
            "type": "string",
            "enum": [
              "VES",
              "COP"
            ]
          },
          "sourceAmount": {
            "type": "string",
            "example": "10000.00",
            "description": "Amount debited (VES to the cent, COP in whole pesos)."
          },
          "sourceAmountVes": {
            "type": "string",
            "example": "10000.00",
            "nullable": true,
            "description": "VES conversions only; `null` for COP."
          },
          "targetAmountUsdt": {
            "type": "string",
            "example": "10.01"
          },
          "origin": {
            "type": "string",
            "enum": [
              "api",
              "auto"
            ],
            "description": "`auto` when created by auto-convert from a pay-in."
          },
          "paymentId": {
            "type": "string",
            "nullable": true,
            "description": "The pay-in an auto-conversion came from; `null` otherwise."
          },
          "createdAt": {
            "type": "string"
          },
          "completedAt": {
            "type": "string",
            "nullable": true
          },
          "canceledAt": {
            "type": "string",
            "nullable": true
          },
          "cancelReason": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "reference",
          "rate",
          "marketRate",
          "spreadPercent",
          "rateSource",
          "sourceCurrency",
          "sourceAmount",
          "sourceAmountVes",
          "targetAmountUsdt",
          "origin",
          "paymentId",
          "createdAt",
          "completedAt",
          "canceledAt",
          "cancelReason"
        ]
      },
      "ConversionListDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversionDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as `cursor` to get the next page."
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      },
      "BankResponseDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "0102",
            "description": "Canonical four-digit SIMF bank code."
          },
          "name": {
            "type": "string",
            "example": "Banco de Venezuela"
          },
          "services": {
            "description": "Provider-reported services; may be empty.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "logoUrl": {
            "type": "string",
            "nullable": true,
            "example": "https://pub-xxxxx.r2.dev/vebanking/banks/0102.png",
            "description": "Public URL for a 100×100 bank logo image (PNG), or null when not uploaded. Render this next to the bank name in selectors so users can identify their bank quickly."
          }
        },
        "required": [
          "code",
          "name",
          "services",
          "logoUrl"
        ]
      },
      "QuoteResponseDto": {
        "type": "object",
        "properties": {
          "usdAmount": {
            "type": "number",
            "example": 25
          },
          "bcvRate": {
            "type": "number",
            "example": 36.5,
            "description": "Official VEX FX BCV rate (Bs per $1)."
          },
          "rate": {
            "type": "number",
            "example": 36.5,
            "description": "Rate your payments are priced at (Bs per $1): `bcvRate` for BCV accounts, the market rate for MARKET accounts."
          },
          "rateSource": {
            "type": "string",
            "enum": [
              "BCV",
              "MARKET"
            ],
            "example": "BCV",
            "description": "Your account's Bolívar rate setting."
          },
          "vesAmount": {
            "type": "number",
            "example": 912.5,
            "description": "usdAmount × rate, rounded to the cent: what a payment created now would charge."
          },
          "medianRate": {
            "type": "number",
            "example": 36.55,
            "description": "Median of available BCV sources (VEX FX + bank)"
          },
          "medianVesAmount": {
            "type": "number",
            "example": 913.75,
            "description": "USD amount converted at medianRate"
          },
          "source": {
            "type": "string",
            "example": "bcv"
          },
          "fetchedAt": {
            "type": "string",
            "format": "date-time"
          },
          "sources": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "vexFx": {
                "rate": 36.5,
                "fetchedAt": "2026-07-23T12:00:00.000Z"
              },
              "bank": {
                "rate": 36.6,
                "fetchedAt": "2026-07-23T12:00:00.000Z"
              }
            },
            "description": "Per-source BCV rates or error objects (e.g. `{ error: \"BANK_NOT_CONFIGURED\" }`). Keys typically include `vexFx` and `bank`. `sources.bank` is the partner-bank BCV rate when available."
          }
        },
        "required": [
          "usdAmount",
          "bcvRate",
          "vesAmount",
          "medianRate",
          "medianVesAmount",
          "source",
          "fetchedAt",
          "sources"
        ]
      },
      "OnwardPayoutDto": {
        "type": "object",
        "properties": {
          "network": {
            "type": "string",
            "example": "BEP20",
            "description": "USDT payout network (see GET /v1/crypto/networks)."
          },
          "address": {
            "type": "string",
            "example": "0x2f5c…",
            "description": "Destination wallet address. Only its format is checked: a wrong but valid address cannot be recovered."
          },
          "tag": {
            "type": "string",
            "description": "Destination tag / memo, for networks that need one (e.g. TON)."
          }
        },
        "required": [
          "network",
          "address"
        ]
      },
      "C2pRequestDto": {
        "type": "object",
        "properties": {
          "usdAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000,
            "example": 25,
            "description": "USD amount. Required unless vesAmount is set. When only usdAmount is set, VES is derived at your Bolívar rate (live BCV, or market if you chose it)."
          },
          "vesAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000000,
            "example": 50,
            "description": "VES amount debited at the bank. When set, locks the bolívar charge and derives USD at your Bolívar rate (it wins over usdAmount). The intent keeps this amount until it is executed."
          },
          "debtorId": {
            "type": "string",
            "example": "V12345678"
          },
          "debtorCellPhone": {
            "type": "string",
            "example": "584121234567",
            "description": "Country code 58 followed by 10 digits."
          },
          "debtorBankCode": {
            "type": "number",
            "example": 102,
            "description": "Venezuelan bank institution code (e.g. 102, 105, 134). Must match a bank from GET /v1/banks."
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "order-1042",
            "description": "Correlation value; not an idempotency key. A ref that already has a COMPLETED payment is refused (409 external_ref_already_paid). When present, any other PENDING C2P intent for this tenant + externalRef is canceled (superseded) before the new intent is created."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "applicationFeeVes": {
            "type": "string",
            "example": "50.00",
            "description": "Marketplace application fee in VES retained by the platform."
          },
          "applicationFeePercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "example": 10,
            "description": "Optional percent of vesAmount used when applicationFeeVes is omitted. When both are omitted and merchantId is set, the merchant's commission (or the tenant default commission) applies."
          },
          "onwardPayout": {
            "description": "Convert this payment's net VES to USDT once it completes and send it to this wallet. Needs USDT and conversions enabled; not allowed with merchantId. See the \"Pay in bolívars, receive USDT\" guide.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnwardPayoutDto"
              }
            ]
          }
        },
        "required": [
          "debtorId",
          "debtorCellPhone",
          "debtorBankCode"
        ]
      },
      "OnwardPayoutStatusDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "converting",
              "waiting_release",
              "sending",
              "completed",
              "held",
              "failed",
              "canceled"
            ],
            "example": "completed",
            "description": "`waiting_release`: converted, waiting for the 24h balance hold to end before sending (see `sendAfter`)."
          },
          "network": {
            "type": "string",
            "example": "BEP20"
          },
          "address": {
            "type": "string",
            "example": "0x2f5c0000000000000000000000000000000000aa"
          },
          "tag": {
            "type": "string"
          },
          "conversionId": {
            "type": "string",
            "format": "uuid",
            "description": "The VES → USDT conversion, once created."
          },
          "payoutId": {
            "type": "string",
            "format": "uuid",
            "description": "The USDT payout, once created."
          },
          "amountUsdt": {
            "type": "string",
            "example": "18.94",
            "description": "USDT sent to the address."
          },
          "feeUsdt": {
            "type": "string",
            "example": "0.75",
            "description": "Network payout fee."
          },
          "txHash": {
            "type": "string",
            "description": "On-chain hash once the payout completed."
          },
          "reason": {
            "type": "string",
            "example": "below_payout_minimum",
            "description": "Why it is held, failed or canceled."
          },
          "sendAfter": {
            "type": "string",
            "format": "date-time",
            "description": "`waiting_release` only: when the converted USDT leaves the balance hold and the payout is sent."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "status",
          "network",
          "address",
          "updatedAt"
        ]
      },
      "C2pIntentResponseDto": {
        "type": "object",
        "properties": {
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "example": "3fd84b2d-9ad1-4f74-a2d9-0f2f56984db5"
          },
          "externalRef": {
            "type": "string",
            "example": "order-1042",
            "description": "Tenant correlation value; not an idempotency key."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "COMPLETED",
              "FAILED",
              "CANCELED",
              "REVERSED"
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "C2P",
              "VPOS",
              "PAGO_MOVIL",
              "DEBITO_INMEDIATO"
            ]
          },
          "usdAmount": {
            "type": "number",
            "example": 25
          },
          "vesAmount": {
            "type": "number",
            "example": 912.5
          },
          "bcvRate": {
            "type": "number",
            "example": 36.5,
            "description": "Official BCV rate (Bs per $1) when the payment was created. Reference only; see `rate`."
          },
          "rate": {
            "type": "number",
            "example": 36.5,
            "description": "Rate (Bs per $1) this payment was priced at: equal to `bcvRate` for BCV tenants, the market rate for MARKET tenants."
          },
          "rateSource": {
            "type": "string",
            "enum": [
              "BCV",
              "MARKET"
            ],
            "example": "BCV",
            "description": "Source of `rate`: the account's Bolívar rate setting when the payment was created."
          },
          "feeUsd": {
            "type": "number",
            "example": 0.88,
            "description": "Platform service fee, USD. Clamped 0..usdAmount."
          },
          "feeVes": {
            "type": "number",
            "example": 32.12,
            "description": "Platform service fee, VES. Clamped 0..vesAmount."
          },
          "netVes": {
            "type": "number",
            "example": 880.38,
            "description": "What the seller receives: vesAmount − platform fee − application fee, floored at 0."
          },
          "bankReference": {
            "type": "string",
            "example": "00512673"
          },
          "bankTxId": {
            "type": "number",
            "example": 842901
          },
          "debtorId": {
            "type": "string",
            "example": "V12345678"
          },
          "debtorPhone": {
            "type": "string",
            "example": "584121234567"
          },
          "debtorBankCode": {
            "type": "number",
            "example": 102
          },
          "debtorBankName": {
            "type": "string",
            "example": "Banco de Venezuela"
          },
          "cardLast4": {
            "type": "string",
            "example": "4242"
          },
          "cardBrand": {
            "type": "string",
            "example": "Visa"
          },
          "cardProduct": {
            "type": "string",
            "example": "Crédito"
          },
          "accountTypeLabel": {
            "type": "string",
            "example": "Cuenta corriente"
          },
          "tenantName": {
            "type": "string",
            "example": "Comercio Demo"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "failureCode": {
            "type": "string",
            "example": "MOVEMENT_NOT_FOUND"
          },
          "cancelReason": {
            "type": "string",
            "enum": [
              "superseded",
              "expired"
            ],
            "description": "Present when status is CANCELED. superseded = replaced by a newer intent; expired = abandoned after TTL."
          },
          "reversedAt": {
            "type": "string",
            "format": "date-time"
          },
          "reversalRef": {
            "type": "string",
            "example": "00991420"
          },
          "reversalTxId": {
            "type": "number",
            "example": 842950
          },
          "onwardPayout": {
            "description": "Present when the pay-in was sent with `onwardPayout`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnwardPayoutStatusDto"
              }
            ]
          },
          "intentId": {
            "type": "string",
            "format": "uuid",
            "description": "Use this value as intentId when executing the C2P charge."
          },
          "otpRequested": {
            "type": "boolean",
            "description": "true when the provider instructed the payer bank to SMS an OTP to the customer. false when the customer must generate the token in their bank app."
          }
        },
        "required": [
          "paymentId",
          "status",
          "method",
          "usdAmount",
          "vesAmount",
          "bcvRate",
          "tenantName",
          "createdAt",
          "intentId",
          "otpRequested"
        ]
      },
      "C2pPaymentDto": {
        "type": "object",
        "properties": {
          "intentId": {
            "type": "string",
            "format": "uuid",
            "description": "Pending intent returned by POST /v1/payments/c2p/request."
          },
          "usdAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000,
            "example": 25,
            "description": "USD amount. Required unless vesAmount or intentId is set. When only usdAmount is set, VES is derived at your Bolívar rate (live BCV, or market if you chose it)."
          },
          "vesAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000000,
            "example": 50,
            "description": "VES amount debited at the bank. When set, locks the bolívar charge and derives USD at your Bolívar rate (it wins over usdAmount). With intentId the amount locked on the intent is charged; amounts sent here must match it (±0.01 Bs / ±$0.01)."
          },
          "debtorId": {
            "type": "string",
            "example": "V12345678"
          },
          "debtorCellPhone": {
            "type": "string",
            "example": "584121234567"
          },
          "debtorBankCode": {
            "type": "number",
            "example": 102,
            "description": "Venezuelan bank institution code (e.g. 102, 105, 134). Must match a bank from GET /v1/banks."
          },
          "token": {
            "type": "string",
            "pattern": "^\\d{6,8}$",
            "example": "123456",
            "description": "Bank-issued token collected by the tenant from the customer."
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "order-1042",
            "description": "Correlation value; not an idempotency key. A ref that already has a COMPLETED payment is refused (409 external_ref_already_paid)."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid",
            "description": "Seller merchant to auto-credit on payment.completed (net = ves − plan fee − applicationFee)."
          },
          "applicationFeeVes": {
            "type": "string",
            "example": "50.00",
            "description": "Marketplace application fee in VES retained by the platform."
          },
          "applicationFeePercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "example": 10,
            "description": "Optional percent of vesAmount used when applicationFeeVes is omitted. When both are omitted and merchantId is set, the merchant's commission (or the tenant default commission) applies."
          },
          "onwardPayout": {
            "description": "Convert this payment's net VES to USDT once it completes and send it to this wallet. Needs USDT and conversions enabled; not allowed with merchantId. See the \"Pay in bolívars, receive USDT\" guide.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnwardPayoutDto"
              }
            ]
          }
        },
        "required": [
          "debtorId",
          "debtorCellPhone",
          "debtorBankCode",
          "token"
        ]
      },
      "PaymentReceiptDto": {
        "type": "object",
        "properties": {
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "example": "3fd84b2d-9ad1-4f74-a2d9-0f2f56984db5"
          },
          "externalRef": {
            "type": "string",
            "example": "order-1042",
            "description": "Tenant correlation value; not an idempotency key."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "COMPLETED",
              "FAILED",
              "CANCELED",
              "REVERSED"
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "C2P",
              "VPOS",
              "PAGO_MOVIL",
              "DEBITO_INMEDIATO"
            ]
          },
          "usdAmount": {
            "type": "number",
            "example": 25
          },
          "vesAmount": {
            "type": "number",
            "example": 912.5
          },
          "bcvRate": {
            "type": "number",
            "example": 36.5,
            "description": "Official BCV rate (Bs per $1) when the payment was created. Reference only; see `rate`."
          },
          "rate": {
            "type": "number",
            "example": 36.5,
            "description": "Rate (Bs per $1) this payment was priced at: equal to `bcvRate` for BCV tenants, the market rate for MARKET tenants."
          },
          "rateSource": {
            "type": "string",
            "enum": [
              "BCV",
              "MARKET"
            ],
            "example": "BCV",
            "description": "Source of `rate`: the account's Bolívar rate setting when the payment was created."
          },
          "feeUsd": {
            "type": "number",
            "example": 0.88,
            "description": "Platform service fee, USD. Clamped 0..usdAmount."
          },
          "feeVes": {
            "type": "number",
            "example": 32.12,
            "description": "Platform service fee, VES. Clamped 0..vesAmount."
          },
          "netVes": {
            "type": "number",
            "example": 880.38,
            "description": "What the seller receives: vesAmount − platform fee − application fee, floored at 0."
          },
          "bankReference": {
            "type": "string",
            "example": "00512673"
          },
          "bankTxId": {
            "type": "number",
            "example": 842901
          },
          "debtorId": {
            "type": "string",
            "example": "V12345678"
          },
          "debtorPhone": {
            "type": "string",
            "example": "584121234567"
          },
          "debtorBankCode": {
            "type": "number",
            "example": 102
          },
          "debtorBankName": {
            "type": "string",
            "example": "Banco de Venezuela"
          },
          "cardLast4": {
            "type": "string",
            "example": "4242"
          },
          "cardBrand": {
            "type": "string",
            "example": "Visa"
          },
          "cardProduct": {
            "type": "string",
            "example": "Crédito"
          },
          "accountTypeLabel": {
            "type": "string",
            "example": "Cuenta corriente"
          },
          "tenantName": {
            "type": "string",
            "example": "Comercio Demo"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "failureCode": {
            "type": "string",
            "example": "MOVEMENT_NOT_FOUND"
          },
          "cancelReason": {
            "type": "string",
            "enum": [
              "superseded",
              "expired"
            ],
            "description": "Present when status is CANCELED. superseded = replaced by a newer intent; expired = abandoned after TTL."
          },
          "reversedAt": {
            "type": "string",
            "format": "date-time"
          },
          "reversalRef": {
            "type": "string",
            "example": "00991420"
          },
          "reversalTxId": {
            "type": "number",
            "example": 842950
          },
          "onwardPayout": {
            "description": "Present when the pay-in was sent with `onwardPayout`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnwardPayoutStatusDto"
              }
            ]
          }
        },
        "required": [
          "paymentId",
          "status",
          "method",
          "usdAmount",
          "vesAmount",
          "bcvRate",
          "tenantName",
          "createdAt"
        ]
      },
      "VposPaymentDto": {
        "type": "object",
        "properties": {
          "usdAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000,
            "example": 25,
            "description": "USD amount. Required unless vesAmount is set. When only usdAmount is set, VES is derived at your Bolívar rate (live BCV, or market if you chose it)."
          },
          "vesAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000000,
            "example": 50,
            "description": "VES amount charged at the bank. When set, locks the bolívar charge and derives USD at your Bolívar rate — use this to avoid USD↔VES 2-decimal round-trip drift (e.g. Bs. 50 → $0.07 → Bs. 52.86)."
          },
          "cardNumber": {
            "type": "string",
            "pattern": "^\\d{13,19}$",
            "example": "4111111111111111",
            "description": "Handle only in a PCI-compliant server environment."
          },
          "expirationMonth": {
            "type": "number",
            "minimum": 1,
            "maximum": 12,
            "example": 12
          },
          "expirationYear": {
            "type": "number",
            "minimum": 2020,
            "maximum": 2099,
            "example": 2028
          },
          "cvv": {
            "type": "string",
            "pattern": "^\\d{3,4}$",
            "example": "123",
            "writeOnly": true
          },
          "cardPin": {
            "type": "string",
            "pattern": "^\\d{4}$",
            "example": "1234",
            "writeOnly": true,
            "description": "Card PIN (4 digits). Optional; defaults to 0000 when omitted."
          },
          "cardHolderName": {
            "type": "string",
            "minLength": 2,
            "maxLength": 80,
            "example": "Maria Perez"
          },
          "cardHolderId": {
            "type": "string",
            "example": "V12345678"
          },
          "accountType": {
            "type": "number",
            "enum": [
              0,
              10,
              20
            ],
            "example": 0,
            "description": "0 credit, 10 savings, 20 checking."
          },
          "cardType": {
            "type": "number",
            "enum": [
              1,
              2,
              3
            ],
            "example": 1,
            "description": "Provider card-brand code."
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "order-1042",
            "description": "Correlation value; not an idempotency key. A ref that already has a COMPLETED payment is refused (409 external_ref_already_paid)."
          },
          "beneficiary": {
            "type": "string",
            "maxLength": 80,
            "example": "@maria",
            "description": "Who the funds are for when that is not a merchant (e.g. the wallet user being topped up). Shown to ops only; does not affect settlement."
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "applicationFeeVes": {
            "type": "string",
            "example": "50.00",
            "description": "Marketplace application fee in VES retained by the platform."
          },
          "applicationFeePercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "example": 10,
            "description": "Optional percent of vesAmount used when applicationFeeVes is omitted. When both are omitted and merchantId is set, the merchant's commission (or the tenant default commission) applies."
          }
        },
        "required": [
          "cardNumber",
          "expirationMonth",
          "expirationYear",
          "cvv",
          "cardHolderName",
          "cardHolderId",
          "accountType",
          "cardType"
        ]
      },
      "PaymentMethodAvailabilityDto": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "pago_movil",
              "c2p",
              "vpos"
            ],
            "description": "`pago_movil`: the customer sends a Pago Móvil (verify). `c2p`: bank debit with the customer's OTP. `vpos`: card."
          },
          "available": {
            "type": "boolean",
            "description": "Whether your account can take this method right now."
          },
          "reason": {
            "type": "string",
            "enum": [
              "not_enabled",
              "receiving_account_not_configured",
              "provider_not_configured"
            ],
            "description": "Only when available is false. `not_enabled`: the method is not enabled on your account. `receiving_account_not_configured`: Pago Móvil receiving details are not set up yet. `provider_not_configured`: temporarily unavailable in this mode — contact support."
          }
        },
        "required": [
          "method",
          "available"
        ]
      },
      "PaymentMethodsResponseDto": {
        "type": "object",
        "properties": {
          "livemode": {
            "type": "boolean",
            "description": "false for test keys."
          },
          "methods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentMethodAvailabilityDto"
            }
          }
        },
        "required": [
          "livemode",
          "methods"
        ]
      },
      "PagoMovilReceivingAccountDto": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "r4",
              "bnc",
              "sofitasa"
            ],
            "example": "r4",
            "description": "Provider Pago Móvil verify uses for this tenant (same routing as POST /v1/payments/pago-movil/verify)."
          },
          "bankCode": {
            "type": "string",
            "example": "0169",
            "description": "Four-digit SIMF code of the receiving bank."
          },
          "bankName": {
            "type": "string",
            "example": "Mi Banco"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "example": "04125555555",
            "description": "Phone the customer sends the Pago Móvil to (11 digits). Null when not configured."
          },
          "identification": {
            "type": "string",
            "nullable": true,
            "example": "13536734",
            "description": "Cédula/RIF of the receiving account, as configured. Null when not configured."
          },
          "configured": {
            "type": "boolean",
            "description": "True when every receiving detail is set. Do not offer Pago Móvil to customers while false."
          },
          "missing": {
            "type": "array",
            "example": [],
            "description": "Receiving details that are not configured yet.",
            "items": {
              "type": "string",
              "enum": [
                "phone",
                "identification"
              ]
            }
          },
          "livemode": {
            "type": "boolean",
            "description": "False for test-mode API keys."
          }
        },
        "required": [
          "provider",
          "bankCode",
          "bankName",
          "phone",
          "identification",
          "configured",
          "missing",
          "livemode"
        ]
      },
      "PagoMovilVerifyDto": {
        "type": "object",
        "properties": {
          "usdAmount": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100000,
            "example": 25
          },
          "reference": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "example": "12345678"
          },
          "dateMovement": {
            "type": "string",
            "format": "date",
            "example": "2026-07-20"
          },
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "order-1042",
            "description": "Correlation value; not an idempotency key."
          },
          "debtorBankCode": {
            "type": "string",
            "example": "0102",
            "description": "Payer bank SIMF code. Required for some receiving banks — send it whenever you have it."
          },
          "txType": {
            "type": "string",
            "enum": [
              "pago_movil",
              "transferencia",
              "debito_inmediato"
            ],
            "example": "transferencia",
            "description": "Instrument type, required by some receiving banks. Defaults to transferencia."
          },
          "debtorCellPhone": {
            "type": "string",
            "example": "04149333844",
            "description": "Payer Pago Móvil phone (11-digit local, e.g. 04149333844). Required by some receiving banks when txType is pago_movil — send it whenever you have it."
          },
          "onwardPayout": {
            "description": "Convert this payment's net VES to USDT once it completes and send it to this wallet. Needs USDT and conversions enabled; not allowed with merchantId. See the \"Pay in bolívars, receive USDT\" guide.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnwardPayoutDto"
              }
            ]
          }
        },
        "required": [
          "usdAmount",
          "reference"
        ]
      },
      "PayoutMethodResponseDto": {
        "type": "object",
        "properties": {
          "payoutMethodId": {
            "type": "string",
            "format": "uuid"
          },
          "bankCode": {
            "type": "string",
            "example": "0134"
          },
          "destination": {
            "type": "string",
            "description": "Masked phone destination, e.g. …5555"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_verification",
              "verifying",
              "verified",
              "rejected"
            ]
          },
          "isDefault": {
            "type": "boolean"
          },
          "failureCode": {
            "type": "string",
            "nullable": true
          },
          "lockedUntil": {
            "type": "string",
            "nullable": true
          },
          "verifiedAt": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "payoutMethodId",
          "bankCode",
          "destination",
          "status",
          "isDefault"
        ]
      },
      "MerchantResponseDto": {
        "type": "object",
        "properties": {
          "merchantId": {
            "type": "string"
          },
          "accountId": {
            "type": "string",
            "example": "acct_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "externalRef": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "maxLength": 20,
            "example": "Maria Perez"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_verification",
              "verifying",
              "verified",
              "rejected"
            ],
            "description": "Mirrored from the default payout method"
          },
          "isActive": {
            "type": "boolean",
            "description": "When false, merchant cannot receive new payouts"
          },
          "autoPayoutEnabled": {
            "type": "boolean",
            "description": "When true, available balance is auto-paid to the default verified method."
          },
          "applicationFeePercent": {
            "type": "number",
            "nullable": true,
            "example": 12.5,
            "description": "Merchant-specific marketplace commission percent. null = the tenant's default commission applies."
          },
          "bankCode": {
            "type": "string",
            "description": "Default method bank code (compat)"
          },
          "destination": {
            "type": "string",
            "description": "Masked default method phone (compat)"
          },
          "payoutMethods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayoutMethodResponseDto"
            }
          },
          "message": {
            "type": "string",
            "description": "Present when the merchant has no payout methods yet (e.g. created without bankCode/phone)",
            "example": "No payout method exists. Add one with POST /v1/merchants/:id/payout-methods before verifying or paying out."
          },
          "failureCode": {
            "type": "string",
            "nullable": true
          },
          "lockedUntil": {
            "type": "string",
            "nullable": true,
            "description": "ISO timestamp; when set and in the future, verification is locked"
          },
          "deactivatedAt": {
            "type": "string",
            "nullable": true,
            "description": "ISO timestamp when the merchant was deactivated"
          },
          "createdAt": {
            "type": "string"
          },
          "verifiedAt": {
            "type": "string",
            "nullable": true
          },
          "ownerType": {
            "type": "string",
            "enum": [
              "tenant",
              "wallet"
            ],
            "description": "How the merchant was created."
          },
          "merchantType": {
            "type": "string",
            "nullable": true,
            "enum": [
              "INDIVIDUAL",
              "COMPANY"
            ]
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "walletUserId": {
            "type": "string",
            "nullable": true,
            "description": "VEX Wallet user id (`ownerType = \"wallet\"`)."
          },
          "rifNumber": {
            "type": "string",
            "nullable": true
          },
          "accountStatus": {
            "type": "string",
            "enum": [
              "active",
              "pending",
              "restricted",
              "rejected"
            ],
            "description": "VEX Pay-owned compliance lifecycle, independent of payout `status`."
          },
          "kybStatus": {
            "type": "string",
            "enum": [
              "not_required",
              "required",
              "pending",
              "verified",
              "rejected"
            ]
          },
          "restrictionReason": {
            "type": "string",
            "nullable": true
          },
          "activatedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "capabilities": {
            "type": "object",
            "nullable": true,
            "description": "Effective payment capabilities (stored grant AND accountStatus = active). Null for merchants with no capabilities row."
          }
        },
        "required": [
          "merchantId",
          "accountId",
          "externalRef",
          "status",
          "isActive"
        ]
      },
      "MerchantListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MerchantResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as cursor on the next request when more pages exist"
          }
        },
        "required": [
          "items"
        ]
      },
      "MerchantAuditEventDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "event": {
            "type": "string",
            "example": "MERCHANT_UPDATED",
            "description": "SCREAMING_SNAKE lifecycle event, e.g. MERCHANT_CREATED | MERCHANT_ACTIVATED | RIF_SUBMITTED | CAPABILITY_ENABLED | MERCHANT_UPDATED | MERCHANT_RESTRICTED."
          },
          "actor": {
            "type": "string",
            "example": "wallet:usr_123",
            "description": "\"wallet:<sub>\" | \"system\" | \"platform:<sub>\"."
          },
          "data": {
            "type": "object",
            "nullable": true,
            "description": "Event-specific detail, e.g. { fields: [\"instagram\"] }."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "event",
          "actor",
          "createdAt"
        ]
      },
      "MerchantAuditEventListDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MerchantAuditEventDto"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "DeleteMerchantResponseDto": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "example": true
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "externalRef": {
            "type": "string",
            "example": "usr_7f3a"
          }
        },
        "required": [
          "deleted",
          "merchantId",
          "externalRef"
        ]
      },
      "PayoutMethodListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayoutMethodResponseDto"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "VerifyStartResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "verifying"
          },
          "expiresAt": {
            "type": "string",
            "example": "2026-07-22T02:30:00Z"
          },
          "payoutMethodId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "status",
          "expiresAt"
        ]
      },
      "VerifyConfirmResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "verified"
          },
          "payoutMethodId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "status",
          "payoutMethodId"
        ]
      },
      "MerchantCopBalanceDto": {
        "type": "object",
        "properties": {
          "pendingCop": {
            "type": "string",
            "example": "16002",
            "description": "COP sales still in the seller hold."
          },
          "availableCop": {
            "type": "string",
            "example": "30000",
            "description": "COP the seller can pay out."
          },
          "payoutPendingCop": {
            "type": "string",
            "example": "0",
            "description": "COP payouts requested and not yet paid."
          },
          "paidOutCop": {
            "type": "string",
            "example": "0",
            "description": "COP paid out to the seller so far."
          },
          "sweepRate": {
            "type": "string",
            "example": "3939.0000",
            "description": "VEX Wallet sellers: COP per US$1 a wallet sweep would use now (display only). Omitted when no fresh rate."
          }
        },
        "required": [
          "pendingCop",
          "availableCop",
          "payoutPendingCop",
          "paidOutCop"
        ]
      },
      "MerchantBalanceDto": {
        "type": "object",
        "properties": {
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "accountId": {
            "type": "string",
            "example": "acct_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "tenantId": {
            "type": "string",
            "format": "uuid"
          },
          "pendingVes": {
            "type": "string",
            "example": "100.00"
          },
          "availableVes": {
            "type": "string",
            "example": "250.00"
          },
          "paidOutVes": {
            "type": "string",
            "example": "50.00"
          },
          "ledgerNetVes": {
            "type": "string",
            "example": "350.00"
          },
          "cop": {
            "description": "COP balances from COP sales on seller links. Present only once the seller has COP activity.",
            "allOf": [
              {
                "$ref": "#/components/schemas/MerchantCopBalanceDto"
              }
            ]
          }
        },
        "required": [
          "merchantId",
          "accountId",
          "tenantId",
          "pendingVes",
          "availableVes",
          "paidOutVes",
          "ledgerNetVes"
        ]
      },
      "CreateMerchantDto": {
        "type": "object",
        "properties": {
          "externalRef": {
            "type": "string",
            "maxLength": 64,
            "example": "usr_7f3a…"
          },
          "name": {
            "type": "string",
            "maxLength": 20,
            "example": "Maria Perez"
          },
          "identification": {
            "type": "string",
            "example": "V12345678",
            "description": "V/E+8 or J/G+9"
          },
          "contactEmail": {
            "type": "string",
            "example": "maria@mail.com"
          },
          "contactPhone": {
            "type": "string",
            "example": "04141234567"
          },
          "bankCode": {
            "type": "string",
            "example": "0134",
            "description": "Optional 4-digit SIMF bank code for the first Pago Móvil payout method. Provide together with phone, or omit both to create a merchant shell with no payout method."
          },
          "phone": {
            "type": "string",
            "example": "04145555555",
            "description": "Optional 11-digit local Pago Móvil phone for the first payout method. Provide together with bankCode, or omit both."
          }
        },
        "required": [
          "externalRef",
          "name",
          "identification",
          "contactEmail",
          "contactPhone"
        ]
      },
      "CreatePayoutMethodDto": {
        "type": "object",
        "properties": {
          "bankCode": {
            "type": "string",
            "example": "0134",
            "description": "4-digit SIMF bank code"
          },
          "phone": {
            "type": "string",
            "example": "04145555555",
            "description": "11-digit local Pago Móvil phone"
          }
        },
        "required": [
          "bankCode",
          "phone"
        ]
      },
      "ConfirmMerchantVerifyDto": {
        "type": "object",
        "properties": {
          "amount1": {
            "type": "string",
            "example": "0.37",
            "description": "Exact two-decimal VES amount"
          },
          "amount2": {
            "type": "string",
            "example": "0.82",
            "description": "Exact two-decimal VES amount"
          }
        },
        "required": [
          "amount1",
          "amount2"
        ]
      },
      "CreateMerchantTransferDto": {
        "type": "object",
        "properties": {
          "amountVes": {
            "type": "string",
            "example": "1523.40",
            "description": "Exact two-decimal VES amount to move from platform float → seller pending."
          },
          "transferKey": {
            "type": "string",
            "maxLength": 64,
            "example": "xfer_bid_1042",
            "description": "Idempotency key for this transfer under the merchant."
          },
          "paymentId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional funding payment correlation (does not enforce remaining-net)."
          }
        },
        "required": [
          "amountVes",
          "transferKey"
        ]
      },
      "UpdateMerchantDto": {
        "type": "object",
        "properties": {
          "isActive": {
            "type": "boolean",
            "description": "Soft off-switch for payouts. false = deactivated (history kept)."
          },
          "autoPayoutEnabled": {
            "type": "boolean",
            "description": "When true, a cron job automatically pays available seller balance to the default verified Pago Móvil method."
          },
          "applicationFeePercent": {
            "type": "number",
            "nullable": true,
            "minimum": 0,
            "maximum": 100,
            "example": 12.5,
            "description": "Negotiated marketplace commission (percent of vesAmount) retained from payments tagged with this merchant when the request sends no applicationFeeVes / applicationFeePercent. null clears the override so the tenant's default commission applies."
          }
        }
      },
      "CreateCheckoutSessionDto": {
        "type": "object",
        "properties": {
          "amountUsd": {
            "type": "number",
            "example": 25,
            "minimum": 0.01,
            "maximum": 100000,
            "description": "USD amount, up to 2 decimals."
          },
          "description": {
            "type": "string",
            "example": "Pedido #1042",
            "maxLength": 200,
            "description": "Buyer-facing label on the checkout."
          },
          "reference": {
            "type": "string",
            "example": "order-1042",
            "maxLength": 64,
            "description": "Your reference, echoed on reads and webhooks."
          },
          "expiresInMinutes": {
            "type": "number",
            "example": 60,
            "minimum": 5,
            "maximum": 1440,
            "default": 60
          },
          "successUrl": {
            "type": "string",
            "example": "https://shop.example/gracias",
            "description": "Where the hosted page sends the buyer after paying. https only (http://localhost allowed for test tenants)."
          },
          "cancelUrl": {
            "type": "string",
            "example": "https://shop.example/carrito",
            "description": "Where a buyer who backs out is sent."
          },
          "allowedOrigins": {
            "example": [
              "https://shop.example"
            ],
            "description": "Origins allowed to embed this checkout with @vexpay/js. https only; http://localhost:* allowed for test tenants. Omit to allow the hosted URL only.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "methods": {
            "type": "array",
            "description": "Payment methods offered. Defaults to every method your account can accept. `c2p` is the bank pull shown as Débito Inmediato; `pago_movil` is a Pago Móvil the buyer sends from their bank app (needs Pago Móvil enabled on your account). `cop` (Colombian pesos: Bre-B, Nequi, Daviplata) needs the COP method on your account.",
            "items": {
              "type": "string",
              "enum": [
                "c2p",
                "pago_movil",
                "vpos",
                "usdt",
                "usdc",
                "cop"
              ]
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "orderId": "1042"
            },
            "description": "Up to 20 string key/value pairs (keys ≤ 40 chars, values ≤ 500 chars)."
          },
          "merchantId": {
            "type": "string",
            "example": "3fd84b2d-9ad1-4f74-a2d9-0f2f56984db5",
            "description": "Split the payment with one of your merchants (UUID or `mrc_` id). The merchant's share is credited to its VES balance when the payment completes. Only bolívar methods (`c2p`, `pago_movil`, `vpos`) are offered."
          },
          "applicationFeePercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "example": 3,
            "description": "Commission percent you keep when `merchantId` is set. Omit to use the merchant's commission, then your default commission."
          }
        },
        "required": [
          "amountUsd"
        ]
      },
      "CheckoutSessionResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cs_4f0c6f1e2b7d4c1a9e3f5a6b7c8d9e0f"
          },
          "object": {
            "type": "string",
            "enum": [
              "checkout.session"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "processing",
              "paid",
              "failed",
              "expired",
              "canceled"
            ],
            "description": "`processing` while a bank charge is in flight; `failed` when the latest attempt failed (the buyer may retry until expiresAt)."
          },
          "clientSecret": {
            "type": "string",
            "description": "Returned only by create. Pass it to @vexpay/js in the browser; never store or log it.",
            "example": "cs-9f2a4b7c1d3e_secret_k8Jc…"
          },
          "url": {
            "type": "string",
            "example": "https://pay.vexwallet.co/pay/cs-9f2a4b7c1d3e"
          },
          "amountUsd": {
            "type": "string",
            "example": "25.00"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "allowedOrigins": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "c2p",
                "pago_movil",
                "vpos",
                "usdt",
                "usdc",
                "cop"
              ]
            }
          },
          "successUrl": {
            "type": "string",
            "nullable": true
          },
          "cancelUrl": {
            "type": "string",
            "nullable": true
          },
          "paymentId": {
            "type": "string",
            "nullable": true,
            "description": "Latest payment for this session, once one exists."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "merchantId": {
            "type": "string",
            "nullable": true,
            "description": "Merchant the payment is split with."
          },
          "applicationFeePercent": {
            "type": "string",
            "nullable": true,
            "example": "3",
            "description": "Commission percent set on the session; null = merchant or tenant default at payment time."
          },
          "livemode": {
            "type": "boolean",
            "description": "false for test-mode tenants."
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "url",
          "amountUsd",
          "metadata",
          "allowedOrigins",
          "methods",
          "expiresAt",
          "createdAt",
          "livemode"
        ]
      },
      "PaymentLinkResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "productId": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string",
            "example": "camiseta-vexpay"
          },
          "hostedCheckoutPath": {
            "type": "string",
            "example": "/pay/camiseta-vexpay",
            "description": "Path of the hosted checkout page."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "allowQuantity": {
            "type": "boolean"
          },
          "maxQuantity": {
            "type": "number",
            "nullable": true
          },
          "redirectUrl": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "productId",
          "slug",
          "hostedCheckoutPath",
          "status",
          "allowQuantity",
          "createdAt"
        ]
      },
      "ProductResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "priceUsd": {
            "type": "string",
            "example": "20.00"
          },
          "active": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentLinkResponseDto"
            }
          }
        },
        "required": [
          "id",
          "name",
          "priceUsd",
          "active",
          "createdAt",
          "updatedAt"
        ]
      },
      "ProductListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as ?cursor= for the next page."
          }
        },
        "required": [
          "items"
        ]
      },
      "PaymentLinkListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentLinkResponseDto"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "CreateProductDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Camiseta VEXPay",
            "maxLength": 120
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          },
          "imageUrl": {
            "type": "string",
            "example": "https://cdn.example/shirt.png"
          },
          "priceUsd": {
            "type": "string",
            "example": "20.00",
            "description": "Positive USD price, up to 2 decimals."
          },
          "active": {
            "type": "boolean",
            "default": true
          }
        },
        "required": [
          "name",
          "priceUsd"
        ]
      },
      "UpdateProductDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "description": {
            "type": "string",
            "maxLength": 2000,
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "priceUsd": {
            "type": "string",
            "example": "25.00"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "CreatePaymentLinkDto": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "URL slug for the hosted checkout. Lowercase letters, digits, hyphens. Auto-generated from the product name when omitted.",
            "example": "camiseta-vexpay"
          },
          "allowQuantity": {
            "type": "boolean",
            "default": false,
            "description": "Let the buyer choose a quantity."
          },
          "maxQuantity": {
            "type": "number",
            "minimum": 1,
            "maximum": 999
          },
          "redirectUrl": {
            "type": "string",
            "description": "Where to send the buyer after a successful payment."
          }
        }
      },
      "UpdatePaymentLinkDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "allowQuantity": {
            "type": "boolean"
          },
          "maxQuantity": {
            "type": "number",
            "minimum": 1,
            "maximum": 999,
            "nullable": true
          },
          "redirectUrl": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "NotificationTestResponseDto": {
        "type": "object",
        "properties": {
          "sent": {
            "type": "boolean",
            "example": true
          },
          "event": {
            "type": "string",
            "example": "notification.test"
          },
          "tenantId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "sent",
          "event",
          "tenantId"
        ]
      },
      "CreateCustomerDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Ana Pérez",
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "nullable": true,
            "example": "ana@example.com",
            "maxLength": 254
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "example": "04141234567",
            "description": "Venezuelan mobile; stored as 11 digits starting with 04."
          },
          "idNumber": {
            "type": "string",
            "nullable": true,
            "example": "V-12.345.678",
            "description": "Cédula or RIF; stored canonical, e.g. V12345678."
          },
          "bankCode": {
            "type": "string",
            "nullable": true,
            "example": "0102",
            "description": "4-digit bank code from GET /v1/banks."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "type": "string"
            },
            "description": "≤ 20 string key/value pairs."
          },
          "testClock": {
            "type": "string",
            "description": "Test clock id (test mode only). Not available yet."
          }
        }
      },
      "CustomerResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cus_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "object": {
            "type": "string",
            "example": "customer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "emailStatus": {
            "type": "string",
            "enum": [
              "none",
              "deliverable",
              "undeliverable"
            ]
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "idNumber": {
            "type": "string",
            "nullable": true
          },
          "bankCode": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "testClock": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string"
          },
          "livemode": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "email",
          "emailStatus",
          "phone",
          "idNumber",
          "bankCode",
          "metadata",
          "testClock",
          "createdAt",
          "livemode"
        ]
      },
      "CustomerListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      },
      "UpdateCustomerDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Ana Pérez",
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "nullable": true,
            "example": "ana@example.com",
            "maxLength": 254
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "example": "04141234567",
            "description": "Venezuelan mobile; stored as 11 digits starting with 04."
          },
          "idNumber": {
            "type": "string",
            "nullable": true,
            "example": "V-12.345.678",
            "description": "Cédula or RIF; stored canonical, e.g. V12345678."
          },
          "bankCode": {
            "type": "string",
            "nullable": true,
            "example": "0102",
            "description": "4-digit bank code from GET /v1/banks."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "type": "string"
            },
            "description": "≤ 20 string key/value pairs."
          },
          "testClock": {
            "type": "string",
            "description": "Test clock id (test mode only). Not available yet."
          }
        }
      },
      "DeletedObjectResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "id",
          "deleted"
        ]
      },
      "RecurringDto": {
        "type": "object",
        "properties": {
          "interval": {
            "type": "string",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ],
            "example": "month"
          },
          "intervalCount": {
            "type": "number",
            "example": 1,
            "default": 1,
            "description": "The whole interval is at most one year."
          }
        },
        "required": [
          "interval"
        ]
      },
      "CreatePriceDto": {
        "type": "object",
        "properties": {
          "product": {
            "type": "string",
            "description": "Product id."
          },
          "unitAmountUsd": {
            "type": "number",
            "example": 10,
            "description": "USD amount, up to 2 decimals, at least the minimum charge."
          },
          "recurring": {
            "$ref": "#/components/schemas/RecurringDto"
          },
          "nickname": {
            "type": "string",
            "maxLength": 80
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": [
          "product",
          "unitAmountUsd",
          "recurring"
        ]
      },
      "PriceRecurringResponseDto": {
        "type": "object",
        "properties": {
          "interval": {
            "type": "string",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ]
          },
          "intervalCount": {
            "type": "number"
          }
        },
        "required": [
          "interval",
          "intervalCount"
        ]
      },
      "PriceResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "price_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "object": {
            "type": "string",
            "example": "price"
          },
          "product": {
            "type": "string"
          },
          "unitAmountUsd": {
            "type": "string",
            "example": "10.00"
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "recurring": {
            "$ref": "#/components/schemas/PriceRecurringResponseDto"
          },
          "nickname": {
            "type": "string",
            "nullable": true
          },
          "active": {
            "type": "boolean"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string"
          },
          "livemode": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "object",
          "product",
          "unitAmountUsd",
          "currency",
          "recurring",
          "nickname",
          "active",
          "metadata",
          "createdAt",
          "livemode"
        ]
      },
      "PriceListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PriceResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      },
      "UpdatePriceDto": {
        "type": "object",
        "properties": {
          "active": {
            "type": "boolean"
          },
          "nickname": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "CreateSubscriptionDto": {
        "type": "object",
        "properties": {
          "customer": {
            "type": "string",
            "description": "Customer id (cus_…)."
          },
          "price": {
            "type": "string",
            "description": "Active recurring price id (price_…)."
          },
          "collectionMethod": {
            "type": "string",
            "enum": [
              "send_invoice",
              "charge_automatically"
            ],
            "default": "send_invoice",
            "description": "`charge_automatically` charges the customer's domiciliación on each collection attempt; the tenant must be allowed domiciliación."
          },
          "collectionAttempts": {
            "type": "number",
            "minimum": 1,
            "maximum": 15,
            "nullable": true,
            "description": "Daily collection attempts on each invoice before the subscription is canceled. Omit or null for the tenant's default (3 unless changed)."
          },
          "paymentMethod": {
            "type": "string",
            "description": "Domiciliación payment method (pm_…, charge_automatically only). Default: the customer's most recent method that is not inactive."
          },
          "trialPeriodDays": {
            "type": "number",
            "minimum": 1,
            "maximum": 730
          },
          "trialEnd": {
            "type": "string",
            "description": "ISO time in the future when the trial ends."
          },
          "cancelAtPeriodEnd": {
            "type": "boolean",
            "default": false
          },
          "methods": {
            "type": "array",
            "description": "Hosted checkout methods offered on its invoices.",
            "items": {
              "type": "string",
              "enum": [
                "c2p",
                "pago_movil",
                "vpos",
                "usdt",
                "usdc",
                "cop"
              ]
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": [
          "customer",
          "price"
        ]
      },
      "SubscriptionResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "sub_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "object": {
            "type": "string",
            "example": "subscription"
          },
          "customer": {
            "type": "string"
          },
          "price": {
            "$ref": "#/components/schemas/PriceResponseDto"
          },
          "status": {
            "type": "string",
            "enum": [
              "trialing",
              "active",
              "past_due",
              "canceled"
            ]
          },
          "collectionMethod": {
            "type": "string",
            "enum": [
              "send_invoice",
              "charge_automatically"
            ]
          },
          "collectionAttempts": {
            "type": "number",
            "nullable": true,
            "description": "Null = the tenant's default."
          },
          "paymentMethod": {
            "type": "string",
            "nullable": true
          },
          "currentPeriodStart": {
            "type": "string"
          },
          "currentPeriodEnd": {
            "type": "string"
          },
          "trialStart": {
            "type": "string",
            "nullable": true
          },
          "trialEnd": {
            "type": "string",
            "nullable": true
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "canceledAt": {
            "type": "string",
            "nullable": true
          },
          "cancellationReason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "requested",
              "payment_failed"
            ]
          },
          "latestInvoice": {
            "type": "string",
            "nullable": true
          },
          "methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "c2p",
                "pago_movil",
                "vpos",
                "usdt",
                "usdc",
                "cop"
              ]
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string"
          },
          "livemode": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "object",
          "customer",
          "price",
          "status",
          "collectionMethod",
          "collectionAttempts",
          "paymentMethod",
          "currentPeriodStart",
          "currentPeriodEnd",
          "trialStart",
          "trialEnd",
          "cancelAtPeriodEnd",
          "canceledAt",
          "cancellationReason",
          "latestInvoice",
          "methods",
          "metadata",
          "createdAt",
          "livemode"
        ]
      },
      "SubscriptionListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SubscriptionResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      },
      "UpdateSubscriptionDto": {
        "type": "object",
        "properties": {
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "collectionMethod": {
            "type": "string",
            "enum": [
              "send_invoice",
              "charge_automatically"
            ]
          },
          "paymentMethod": {
            "type": "string"
          },
          "collectionAttempts": {
            "type": "number",
            "minimum": 1,
            "maximum": 15,
            "nullable": true,
            "description": "null = the tenant's default."
          },
          "methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "c2p",
                "pago_movil",
                "vpos",
                "usdt",
                "usdc",
                "cop"
              ]
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "InvoiceBillingFeeResponseDto": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "string",
            "example": "43.90"
          },
          "currency": {
            "type": "string",
            "enum": [
              "VES",
              "USDT",
              "USDC",
              "COP"
            ]
          },
          "percent": {
            "type": "string",
            "example": "0.5"
          }
        },
        "required": [
          "amount",
          "currency",
          "percent"
        ]
      },
      "InvoiceResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "in_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "object": {
            "type": "string",
            "example": "invoice"
          },
          "number": {
            "type": "string",
            "example": "K7Q2M9XA-0001"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "paid",
              "void",
              "uncollectible"
            ]
          },
          "customer": {
            "type": "string"
          },
          "subscription": {
            "type": "string"
          },
          "collectionMethod": {
            "type": "string",
            "enum": [
              "send_invoice",
              "charge_automatically"
            ]
          },
          "amountDueUsd": {
            "type": "string",
            "example": "10.00"
          },
          "amountPaidUsd": {
            "type": "string",
            "example": "0.00"
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "periodStart": {
            "type": "string"
          },
          "periodEnd": {
            "type": "string"
          },
          "dueDate": {
            "type": "string",
            "description": "Invoices are due when issued."
          },
          "attemptsTotal": {
            "type": "number",
            "description": "Daily collection attempts for this invoice."
          },
          "attemptCount": {
            "type": "number"
          },
          "nextPaymentAttempt": {
            "type": "string",
            "nullable": true
          },
          "paidAt": {
            "type": "string",
            "nullable": true
          },
          "paidOutOfBand": {
            "type": "boolean"
          },
          "paymentId": {
            "type": "string",
            "nullable": true
          },
          "billingFee": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/InvoiceBillingFeeResponseDto"
              }
            ]
          },
          "hostedInvoiceUrl": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string"
          },
          "livemode": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "object",
          "number",
          "status",
          "customer",
          "subscription",
          "collectionMethod",
          "amountDueUsd",
          "amountPaidUsd",
          "currency",
          "periodStart",
          "periodEnd",
          "dueDate",
          "attemptsTotal",
          "attemptCount",
          "nextPaymentAttempt",
          "paidAt",
          "paidOutOfBand",
          "paymentId",
          "billingFee",
          "hostedInvoiceUrl",
          "createdAt",
          "livemode"
        ]
      },
      "InvoiceListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InvoiceResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      },
      "PayInvoiceDto": {
        "type": "object",
        "properties": {
          "paidOutOfBand": {
            "type": "boolean",
            "example": true,
            "description": "Mark the invoice paid outside VEXPay (cash, transfer). No balance change."
          }
        },
        "required": [
          "paidOutOfBand"
        ]
      },
      "CreateSetupSessionDto": {
        "type": "object",
        "properties": {
          "customer": {
            "type": "string",
            "description": "Customer id (cus_…)."
          },
          "successUrl": {
            "type": "string",
            "description": "Where the setup page sends the customer when done (https).",
            "maxLength": 2048
          }
        },
        "required": [
          "customer"
        ]
      },
      "SetupSessionResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "seti_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "object": {
            "type": "string",
            "example": "setup_session"
          },
          "url": {
            "type": "string",
            "nullable": true,
            "description": "Hosted authorization page. Only returned on create."
          },
          "customer": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "complete",
              "expired"
            ]
          },
          "paymentMethod": {
            "type": "string",
            "nullable": true
          },
          "successUrl": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string"
          },
          "createdAt": {
            "type": "string"
          },
          "livemode": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "object",
          "url",
          "customer",
          "status",
          "paymentMethod",
          "successUrl",
          "expiresAt",
          "createdAt",
          "livemode"
        ]
      },
      "PaymentMethodResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "pm_3fd84b2d9ad14f74a2d90f2f56984db5"
          },
          "object": {
            "type": "string",
            "example": "payment_method"
          },
          "type": {
            "type": "string",
            "example": "domiciliacion"
          },
          "customer": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "inactive"
            ],
            "description": "pending until a charge succeeds; inactive when the bank reports the affiliation inactive."
          },
          "phoneLast4": {
            "type": "string",
            "example": "4567"
          },
          "bankCode": {
            "type": "string",
            "example": "0102"
          },
          "createdAt": {
            "type": "string"
          },
          "activatedAt": {
            "type": "string",
            "nullable": true
          },
          "deactivatedAt": {
            "type": "string",
            "nullable": true
          },
          "detachedAt": {
            "type": "string",
            "nullable": true,
            "description": "Set once detached; a detached method is never charged."
          },
          "livemode": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "object",
          "type",
          "customer",
          "status",
          "phoneLast4",
          "bankCode",
          "createdAt",
          "activatedAt",
          "deactivatedAt",
          "detachedAt",
          "livemode"
        ]
      },
      "PaymentMethodListResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentMethodResponseDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "items",
          "nextCursor"
        ]
      }
    }
  }
}
