{ "openapi": "3.1.0", "info": { "title": "YuvexPay API", "description": "The YuvexPay API allows you to accept payments, process withdrawals, manage products and customers programmatically. All API access is over HTTPS and uses JSON request/response bodies.", "version": "1.0.0", "contact": { "name": "YuvexPay Support", "email": "support@yuvexpay.com", "url": "https://docs.yuvexpay.com" } }, "servers": [ { "url": "https://api.yuvexpay.com", "description": "Same base URL serves both sandbox and production. Send a `ypk_test_*` key for sandbox or a `ypk_live_*` key for production." } ], "security": [ { "bearerAuth": [] } ], "tags": [ { "name": "Authentication", "description": "Inspect the API key in use" }, { "name": "Payments", "description": "Create and manage payments" }, { "name": "Withdrawals", "description": "Create and manage withdrawals" }, { "name": "Products", "description": "Manage product catalog" }, { "name": "Customers", "description": "Manage customer records" }, { "name": "Documents", "description": "Generate receipts and statements" }, { "name": "Balance", "description": "Inspect the current account balance" } ], "paths": { "/v1/auth/self": { "get": { "operationId": "getApiKeySelf", "summary": "Inspect the current API key", "description": "Return metadata about the API key currently being used: id, name, environment, scopes, IP allowlist, last-used timestamp and expiration. Useful for verifying key configuration without storing it client-side.", "tags": [ "Authentication" ], "responses": { "200": { "description": "API key metadata.", "content": { "application/json": { "schema": { "type": "object", "properties": { "apiKey": { "$ref": "#/components/schemas/ApiKeySelf" } } }, "example": { "apiKey": { "id": "5d0f8b6e-3a02-4f5b-9e1c-7c6a4a1b8c9d", "name": "Backend integration", "description": null, "environment": "PRODUCTION", "prefix": "ypk_live_ab12cd34ef", "scopes": [ "payments:write", "payments:read", "withdrawals:write", "withdrawals:read" ], "ipAllowlist": [ "203.0.113.10" ], "rateLimitPerMinute": 600, "expiresAt": null, "lastUsedAt": "2026-05-03T14:21:08.443Z", "createdAt": "2026-04-12T09:00:00.000Z" } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } } } }, "/v1/payments": { "post": { "operationId": "createPayment", "summary": "Create a payment", "description": "Create a new payment. Supports PIX, direct credit card charges for headless single-method CARD flows, hosted card checkout, and boleto. Requires an idempotency key.", "tags": [ "Payments" ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePaymentRequest" }, "example": { "amount": 49.9, "methods": [ "PIX" ], "currency": "BRL", "mode": "headless", "description": "Order #1234", "externalId": "order-1234", "expiresInMinutes": 30, "customer": { "name": "Pedro Álvares Cabral", "email": "user@example.com", "phone": "+5511999999999", "document": "12345678900" }, "metadata": { "order_id": "1234", "source": "website" } }, "examples": { "headlessPix": { "summary": "Headless PIX payment", "value": { "amount": 49.9, "methods": [ "PIX" ], "currency": "BRL", "mode": "headless", "description": "Order #1234", "externalId": "order-1234", "expiresInMinutes": 30, "customer": { "name": "Pedro Álvares Cabral", "email": "user@example.com", "phone": "+5511999999999", "document": "12345678900" }, "metadata": { "order_id": "1234", "source": "website" } } }, "headlessCardDirect": { "summary": "Headless direct credit CARD payment", "value": { "amount": 149.9, "methods": [ "CARD" ], "currency": "BRL", "mode": "headless", "description": "Order #5678", "externalId": "order-5678", "customer": { "name": "Pedro Álvares Cabral", "email": "user@example.com", "phone": "+5511999999999", "document": "12345678900" }, "card": { "number": "4111111111111111", "expiryMonth": "12", "expiryYear": "2030", "ccv": "123", "installments": 1, "remoteIp": "198.51.100.23", "holderInfo": { "postalCode": "01310930", "addressNumber": "100", "phone": "+5511999999999" } } } } } } } }, "responses": { "201": { "description": "Payment created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePaymentResponse" }, "examples": { "headlessPix": { "summary": "Headless PIX payment", "value": { "payment": { "id": "5d0f8b6e-3a02-4f5b-9e1c-7c6a4a1b8c9d", "txId": "PAY3f2a8b9c4e6d1f5a7b3c8d2e9f4a6b1c", "amount": 49.9, "feeAmount": 2.99, "netAmount": 46.91, "status": "NEW", "paymentMethod": "PIX", "currency": "BRL", "description": "Order #1234", "expiresAt": "2026-05-03T15:00:00.000Z", "createdAt": "2026-05-03T14:30:00.000Z", "methodData": { "type": "PIX", "pixCopyPaste": "00020126...", "qrCodeBase64": "data:image/png;base64,...", "qrCodeUrl": null } } } }, "headlessCardDirect": { "summary": "Headless direct credit CARD payment", "value": { "payment": { "id": "8f3c0a85-7c29-4e3a-9e07-5b1a7b6d1234", "txId": "PAYa1b2c3d4e5f60718293a4b5c6d7e8f90", "amount": 149.9, "feeAmount": 8.25, "netAmount": 141.65, "status": "PROCESSING", "paymentMethod": "CARD", "currency": "BRL", "description": "Order #5678", "expiresAt": "2026-05-03T15:00:00.000Z", "createdAt": "2026-05-03T14:30:00.000Z", "methodData": { "type": "CARD", "captureType": "DIRECT", "cardSubtype": "CREDIT", "brand": "VISA", "last4Digits": "1111", "installments": 1 } } } }, "hostedCheckout": { "summary": "Hosted multi-method checkout", "value": { "payment": { "id": "fa1c0a85-7c29-4e3a-9e07-5b1a7b6d1234", "txId": "PAY9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e", "amount": 49.9, "feeAmount": 2.99, "netAmount": 46.91, "status": "PENDING_METHOD_SELECTION", "methods": [ "PIX", "CARD" ], "currency": "BRL", "checkoutUrl": "https://checkout.yuvexpay.com/checkout/fa1c0a85-7c29-4e3a-9e07-5b1a7b6d1234", "expiresAt": "2026-05-03T15:00:00.000Z", "isSandbox": true, "createdAt": "2026-05-03T14:30:00.000Z" } } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "409": { "$ref": "#/components/responses/IdempotencyConflict" }, "429": { "$ref": "#/components/responses/RateLimited" } } }, "get": { "operationId": "listPayments", "summary": "List payments", "description": "Retrieve a paginated list of payments with optional filters.", "tags": [ "Payments" ], "parameters": [ { "name": "status", "in": "query", "schema": { "$ref": "#/components/schemas/PaymentStatus" }, "description": "Filter by payment status." }, { "name": "method", "in": "query", "schema": { "$ref": "#/components/schemas/PaymentMethod" }, "description": "Filter by payment method." }, { "name": "startDate", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "Start of date range (ISO 8601)." }, { "name": "endDate", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "End of date range (ISO 8601)." }, { "name": "minAmount", "in": "query", "schema": { "type": "number" }, "description": "Minimum payment amount." }, { "name": "maxAmount", "in": "query", "schema": { "type": "number" }, "description": "Maximum payment amount." }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Limit" } ], "responses": { "200": { "description": "Payments listed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "payments": { "type": "array", "items": { "$ref": "#/components/schemas/Payment" } }, "pagination": { "$ref": "#/components/schemas/Pagination" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/RateLimited" } } } }, "/v1/payments/{paymentId}": { "get": { "operationId": "getPayment", "summary": "Get a payment", "description": "Retrieve a single payment by its ID.", "tags": [ "Payments" ], "parameters": [ { "name": "paymentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The payment ID." } ], "responses": { "200": { "description": "Payment found.", "content": { "application/json": { "schema": { "type": "object", "properties": { "payment": { "$ref": "#/components/schemas/Payment" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/payments/txid/{txId}": { "get": { "operationId": "getPaymentByTxId", "summary": "Get payment by transaction ID", "description": "Retrieve a payment using the YuvexPay transaction ID (`txId`) instead of the UUID.", "tags": [ "Payments" ], "parameters": [ { "name": "txId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The YuvexPay transaction ID." } ], "responses": { "200": { "description": "Payment found.", "content": { "application/json": { "schema": { "type": "object", "properties": { "payment": { "$ref": "#/components/schemas/Payment" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/payments/{paymentId}/boleto": { "get": { "operationId": "getPaymentBoleto", "summary": "Download boleto PDF", "description": "Download the boleto PDF for a payment whose method is BOLETO. The response is the PDF binary; clients should treat the body as `application/pdf`.", "tags": [ "Payments" ], "parameters": [ { "name": "paymentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The payment ID." } ], "responses": { "200": { "description": "Boleto PDF.", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/payments/{paymentId}/refund": { "post": { "operationId": "refundPayment", "summary": "Refund a payment", "description": "Issue a full or partial refund for a paid payment. Requires an idempotency key.", "tags": [ "Payments" ], "parameters": [ { "name": "paymentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The payment ID to refund." }, { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefundPaymentRequest" }, "example": { "amount": 25, "reason": "Customer requested refund" } } } }, "responses": { "200": { "description": "Refund created.", "content": { "application/json": { "schema": { "type": "object", "properties": { "refund": { "$ref": "#/components/schemas/Refund" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/IdempotencyConflict" } } } }, "/v1/payments/{paymentId}/refunds": { "get": { "operationId": "listRefunds", "summary": "List refunds", "description": "Retrieve all refunds for a specific payment.", "tags": [ "Payments" ], "parameters": [ { "name": "paymentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The payment ID." } ], "responses": { "200": { "description": "Refunds listed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "refunds": { "type": "array", "items": { "$ref": "#/components/schemas/Refund" } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/withdrawals": { "post": { "operationId": "createWithdrawal", "summary": "Create a withdrawal", "description": "Create a PIX withdrawal to transfer BRL funds from your YuvexPay balance. Requires an idempotency key.\n\nThe PIX key type (CPF, CNPJ, e-mail, phone, or random key) is detected automatically from `destination.pixKey` — you do not need to declare it. Invalid keys are rejected with `INVALID_PIX_KEY`.\n\nThe creditor document on the network is always derived server-side from your verified company tax id (CNPJ for business accounts, owner CPF for individual accounts).\n\nWithdrawals may be blocked outside business hours or if your account has restrictions.", "tags": [ "Withdrawals" ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateWithdrawalRequest" }, "examples": { "pix": { "summary": "PIX withdrawal", "value": { "amount": 500, "method": "PIX", "currency": "BRL", "destination": { "type": "pix", "pixKey": "ana@example.com" }, "description": "Weekly payout" } } } } } }, "responses": { "201": { "description": "Withdrawal created.", "content": { "application/json": { "schema": { "type": "object", "properties": { "withdrawal": { "$ref": "#/components/schemas/Withdrawal" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "description": "Withdrawals blocked for this account.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "$ref": "#/components/responses/IdempotencyConflict" }, "429": { "$ref": "#/components/responses/RateLimited" } } }, "get": { "operationId": "listWithdrawals", "summary": "List withdrawals", "description": "Retrieve a paginated list of withdrawals with optional filters.", "tags": [ "Withdrawals" ], "parameters": [ { "name": "status", "in": "query", "schema": { "$ref": "#/components/schemas/WithdrawalStatus" }, "description": "Filter by withdrawal status." }, { "name": "method", "in": "query", "schema": { "type": "string", "enum": [ "PIX" ] }, "description": "Filter by withdrawal method. Public withdrawals currently support PIX only." }, { "name": "currency", "in": "query", "schema": { "type": "string", "enum": [ "BRL" ] }, "description": "Filter by currency. Public withdrawals currently support BRL only." }, { "name": "startDate", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "Start of date range (ISO 8601)." }, { "name": "endDate", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "End of date range (ISO 8601)." }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Limit" } ], "responses": { "200": { "description": "Withdrawals listed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "withdrawals": { "type": "array", "items": { "$ref": "#/components/schemas/Withdrawal" } }, "pagination": { "$ref": "#/components/schemas/Pagination" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/RateLimited" } } } }, "/v1/withdrawals/limits": { "get": { "operationId": "getWithdrawalLimits", "summary": "Get withdrawal limits", "description": "Retrieve your current daily withdrawal limits, usage, and fee information. Limits are reduced during nighttime hours (22:00-06:00 BRT).", "tags": [ "Withdrawals" ], "responses": { "200": { "description": "Limits retrieved.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WithdrawalLimits" }, "example": { "currentLimit": 5000, "used": 1200, "remaining": 3800, "isNightTime": false, "fee": 2.49, "dayStartHour": 6, "dayEndHour": 22 } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } } } }, "/v1/withdrawals/{withdrawalId}": { "get": { "operationId": "getWithdrawal", "summary": "Get a withdrawal", "description": "Retrieve a single withdrawal by its ID.", "tags": [ "Withdrawals" ], "parameters": [ { "name": "withdrawalId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The withdrawal ID." } ], "responses": { "200": { "description": "Withdrawal found.", "content": { "application/json": { "schema": { "type": "object", "properties": { "withdrawal": { "$ref": "#/components/schemas/Withdrawal" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/balance": { "get": { "operationId": "getBalance", "summary": "Get account balance", "description": "Return the current BRL balance for the company associated with the API key. The endpoint takes no parameters — the company is always derived from the API key. The three balance buckets are independent and additive: `available` (withdrawable now), `frozen` (reserved for in-flight withdrawals, refunds, or operational holds — not currently withdrawable), and `held` (confirmed but pending settlement). The total account balance is `available + frozen + held`. A sandbox API key always returns zeros, since sandbox transactions do not accumulate to a real balance.", "tags": [ "Balance" ], "responses": { "200": { "description": "Balance retrieved.", "content": { "application/json": { "schema": { "type": "object", "properties": { "balance": { "$ref": "#/components/schemas/Balance" } }, "required": [ "balance" ] }, "examples": { "noFrozenFunds": { "summary": "Production balance with nothing frozen", "value": { "balance": { "available": 13.45, "frozen": 0, "held": 10.2, "total": 23.65, "currency": "BRL", "environment": "PRODUCTION", "updatedAt": "2026-05-06T12:00:00.000Z" } } }, "withFrozenFunds": { "summary": "Production balance with funds frozen for an in-flight withdrawal", "value": { "balance": { "available": 6.47, "frozen": 6.99, "held": 10.2, "total": 23.66, "currency": "BRL", "environment": "PRODUCTION", "updatedAt": "2026-05-06T12:00:00.000Z" } } }, "sandboxKey": { "summary": "Sandbox API key — always returns zeros", "value": { "balance": { "available": 0, "frozen": 0, "held": 0, "total": 0, "currency": "BRL", "environment": "SANDBOX", "updatedAt": null } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/RateLimited" } } } }, "/v1/products": { "post": { "operationId": "createProduct", "summary": "Create a product", "description": "Create a new product in your catalog. Products can be referenced when creating payments to pre-fill amount and description.", "tags": [ "Products" ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateProductRequest" }, "example": { "name": "Premium Plan", "description": "Monthly premium subscription", "amount": 99.9, "externalId": "plan-premium", "metadata": { "tier": "premium", "billing": "monthly" } } } } }, "responses": { "201": { "description": "Product created.", "content": { "application/json": { "schema": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "409": { "$ref": "#/components/responses/IdempotencyConflict" } } }, "get": { "operationId": "listProducts", "summary": "List products", "description": "Retrieve a paginated list of products with optional search and filters.", "tags": [ "Products" ], "parameters": [ { "name": "search", "in": "query", "schema": { "type": "string" }, "description": "Search products by name." }, { "name": "isActive", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] }, "description": "Filter by active status." }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Limit" } ], "responses": { "200": { "description": "Products listed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "products": { "type": "array", "items": { "$ref": "#/components/schemas/Product" } }, "pagination": { "$ref": "#/components/schemas/Pagination" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } } } }, "/v1/products/{productId}": { "get": { "operationId": "getProduct", "summary": "Get a product", "description": "Retrieve a single product by its ID.", "tags": [ "Products" ], "parameters": [ { "name": "productId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The product ID." } ], "responses": { "200": { "description": "Product found.", "content": { "application/json": { "schema": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "patch": { "operationId": "updateProduct", "summary": "Update a product", "description": "Update one or more fields of an existing product.", "tags": [ "Products" ], "parameters": [ { "name": "productId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The product ID." } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateProductRequest" } } } }, "responses": { "200": { "description": "Product updated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" }, "message": { "type": "string" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "delete": { "operationId": "deleteProduct", "summary": "Deactivate a product", "description": "Soft-delete a product by setting it as inactive. The product data is preserved but it can no longer be used in new payments.", "tags": [ "Products" ], "parameters": [ { "name": "productId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The product ID." } ], "responses": { "200": { "description": "Product deactivated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/products/{productId}/image": { "post": { "operationId": "uploadProductImage", "summary": "Upload product image", "description": "Upload (or replace) the image for a product. Send a single file as `multipart/form-data`. Accepted formats: PNG, JPEG. Maximum 10 MB.", "tags": [ "Products" ], "parameters": [ { "name": "productId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The product ID." } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary", "description": "Image file (PNG or JPEG, max 10 MB)." } }, "required": [ "file" ] } } } }, "responses": { "200": { "description": "Image uploaded.", "content": { "application/json": { "schema": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "delete": { "operationId": "deleteProductImage", "summary": "Delete product image", "description": "Remove the image associated with a product.", "tags": [ "Products" ], "parameters": [ { "name": "productId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The product ID." } ], "responses": { "200": { "description": "Image removed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/products/external/{externalId}": { "get": { "operationId": "getProductByExternalId", "summary": "Get product by external ID", "description": "Retrieve a product using your own external ID instead of the YuvexPay UUID.", "tags": [ "Products" ], "parameters": [ { "name": "externalId", "in": "path", "required": true, "schema": { "type": "string", "maxLength": 100 }, "description": "Your external product ID." } ], "responses": { "200": { "description": "Product found.", "content": { "application/json": { "schema": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/customers": { "post": { "operationId": "createCustomer", "summary": "Create a customer", "description": "Create a new customer record. Customers can be associated with payments for tracking and recurring billing.", "tags": [ "Customers" ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateCustomerRequest" }, "example": { "name": "Pedro Álvares Cabral", "email": "user@example.com", "document": "12345678900", "documentType": "CPF", "phone": "+5511999999999", "externalId": "cust-001", "metadata": { "plan": "premium" } } } } }, "responses": { "201": { "description": "Customer created.", "content": { "application/json": { "schema": { "type": "object", "properties": { "customer": { "$ref": "#/components/schemas/Customer" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "409": { "$ref": "#/components/responses/IdempotencyConflict" } } }, "get": { "operationId": "listCustomers", "summary": "List customers", "description": "Retrieve a paginated list of customers with optional search and filters.", "tags": [ "Customers" ], "parameters": [ { "name": "search", "in": "query", "schema": { "type": "string" }, "description": "Search by name, email, or document." }, { "name": "isActive", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] }, "description": "Filter by active status." }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Limit" } ], "responses": { "200": { "description": "Customers listed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "customers": { "type": "array", "items": { "$ref": "#/components/schemas/Customer" } }, "pagination": { "$ref": "#/components/schemas/Pagination" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } } } }, "/v1/customers/{customerId}": { "get": { "operationId": "getCustomer", "summary": "Get a customer", "description": "Retrieve a single customer by their ID, including metadata.", "tags": [ "Customers" ], "parameters": [ { "name": "customerId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The customer's prefixed identifier (e.g., `cus_ab12cd34ef`). This is the merchant-facing slug, not the internal UUID." } ], "responses": { "200": { "description": "Customer found.", "content": { "application/json": { "schema": { "type": "object", "properties": { "customer": { "$ref": "#/components/schemas/CustomerDetail" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "patch": { "operationId": "updateCustomer", "summary": "Update a customer", "description": "Update one or more fields of an existing customer.", "tags": [ "Customers" ], "parameters": [ { "name": "customerId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The customer's prefixed identifier (e.g., `cus_ab12cd34ef`). This is the merchant-facing slug, not the internal UUID." } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateCustomerRequest" } } } }, "responses": { "200": { "description": "Customer updated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "customer": { "$ref": "#/components/schemas/Customer" }, "message": { "type": "string" } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } }, "delete": { "operationId": "deleteCustomer", "summary": "Deactivate a customer", "description": "Soft-delete a customer by setting them as inactive. Customer data is preserved.", "tags": [ "Customers" ], "parameters": [ { "name": "customerId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The customer's prefixed identifier (e.g., `cus_ab12cd34ef`). This is the merchant-facing slug, not the internal UUID." } ], "responses": { "200": { "description": "Customer deactivated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/documents/payments/{paymentId}/receipt": { "get": { "operationId": "getPaymentReceipt", "summary": "Get payment receipt", "description": "Generate a receipt document for a specific payment. Available in HTML or plain text format.", "tags": [ "Documents" ], "parameters": [ { "name": "paymentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The payment ID." }, { "name": "format", "in": "query", "schema": { "type": "string", "enum": [ "html", "text" ], "default": "html" }, "description": "Output format." } ], "responses": { "200": { "description": "Receipt generated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "type": "string", "description": "The receipt content in the requested format." } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/documents/withdrawals/{withdrawalId}/receipt": { "get": { "operationId": "getWithdrawalReceipt", "summary": "Get withdrawal receipt", "description": "Generate a receipt document for a specific withdrawal. Available in HTML or plain text format.", "tags": [ "Documents" ], "parameters": [ { "name": "withdrawalId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The withdrawal ID." }, { "name": "format", "in": "query", "schema": { "type": "string", "enum": [ "html", "text" ], "default": "html" }, "description": "Output format." } ], "responses": { "200": { "description": "Receipt generated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "type": "string", "description": "The receipt content in the requested format." } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } } } }, "/v1/documents/statements": { "get": { "operationId": "getStatement", "summary": "Get account statement", "description": "Generate an account statement for a date range. Maximum range is 90 days.", "tags": [ "Documents" ], "parameters": [ { "name": "startDate", "in": "query", "required": true, "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }, "description": "Start date in `YYYY-MM-DD` format.", "example": "2026-01-01" }, { "name": "endDate", "in": "query", "required": true, "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }, "description": "End date in `YYYY-MM-DD` format.", "example": "2026-01-31" }, { "name": "format", "in": "query", "schema": { "type": "string", "enum": [ "html", "text" ], "default": "html" }, "description": "Output format." } ], "responses": { "200": { "description": "Statement generated.", "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "type": "string", "description": "The statement content in the requested format." } } } } } }, "400": { "$ref": "#/components/responses/ValidationError" }, "401": { "$ref": "#/components/responses/Unauthorized" } } } } }, "webhooks": { "payment.confirmed": { "post": { "summary": "Payment confirmed", "description": "Card or boleto payment was authorized by the issuer. Funds are held as receivable but not yet settled.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" }, "example": { "id": "evt_xyz789", "type": "PAYMENT_CONFIRMED", "data": { "id": "5d0f8b6e-3a02-4f5b-9e1c-7c6a4a1b8c9d", "txId": "PAY3f2a8b9c4e6d1f5a7b3c8d2e9f4a6b1c", "status": "CONFIRMED", "amount": 149.9 } } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "payment.paid": { "post": { "summary": "Payment paid", "description": "Funds were received and the net amount was credited to your balance.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" }, "example": { "id": "evt_xyz789", "type": "PAYMENT_PAID", "data": { "id": "5d0f8b6e-3a02-4f5b-9e1c-7c6a4a1b8c9d", "txId": "PAY3f2a8b9c4e6d1f5a7b3c8d2e9f4a6b1c", "status": "PAID", "amount": 49.9 } } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "payment.expired": { "post": { "summary": "Payment expired", "description": "Triggered when a payment expires before being completed.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "payment.refunded": { "post": { "summary": "Payment refunded", "description": "A refund completed for this payment.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "payment.refund_failed": { "post": { "summary": "Payment refund failed", "description": "A refund attempt could not be executed. The funds are returned to your balance and you may retry.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "payment.chargeback": { "post": { "summary": "Payment chargeback", "description": "A chargeback was opened or processed against this payment.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "med.received": { "post": { "summary": "PIX MED received", "description": "A PIX MED (special refund mechanism) request was opened by the payer's bank. Funds for the affected payment are temporarily held.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "med.resolved": { "post": { "summary": "PIX MED resolved", "description": "A PIX MED request was resolved (approved or rejected).", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "withdrawal.requested": { "post": { "summary": "Withdrawal requested", "description": "A withdrawal was created and is being processed.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "withdrawal.sent": { "post": { "summary": "Withdrawal sent", "description": "Triggered when a withdrawal is successfully processed.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } }, "withdrawal.failed": { "post": { "summary": "Withdrawal failed", "description": "Triggered when a withdrawal fails to process.", "tags": [ "Webhooks" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookEvent" } } } }, "responses": { "200": { "description": "Return a 2xx status to acknowledge receipt." } } } } }, "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "description": "YuvexPay API key. Include as `Authorization: Bearer ypk___` where `` is `test` (sandbox) or `live` (production). Create and manage keys in the dashboard under **Settings > API Keys**." } }, "parameters": { "IdempotencyKey": { "name": "X-Idempotency-Key", "in": "header", "required": true, "schema": { "type": "string", "maxLength": 100 }, "description": "A unique string to ensure the request is processed only once. Must be unique per request. Valid for 24 hours." }, "Page": { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number for pagination." }, "Limit": { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }, "description": "Number of items per page (1-100)." } }, "schemas": { "PaymentMethod": { "type": "string", "enum": [ "PIX", "CARD", "BOLETO" ], "description": "Available public payment methods." }, "Currency": { "type": "string", "enum": [ "BRL" ], "description": "Supported currencies." }, "PaymentStatus": { "type": "string", "enum": [ "NEW", "PENDING_METHOD_SELECTION", "PROCESSING", "CONFIRMED", "PAID", "CANCELLED", "EXPIRED", "REFUNDED", "PARTIAL_REFUND", "CHARGEBACK", "MED_FROZEN" ], "description": "Possible payment statuses." }, "WithdrawalStatus": { "type": "string", "enum": [ "PENDING", "PROCESSING", "COMPLETED", "FAILED", "CANCELLED" ], "description": "Possible withdrawal statuses." }, "TransactionStatus": { "type": "string", "enum": [ "PENDING", "PROCESSING", "COMPLETED", "FAILED", "CANCELLED", "REFUNDED" ], "description": "Generic transaction status." }, "WebhookEventType": { "type": "string", "enum": [ "PAYMENT_CONFIRMED", "PAYMENT_PAID", "PAYMENT_EXPIRED", "PAYMENT_REFUNDED", "PAYMENT_REFUND_FAILED", "PAYMENT_CHARGEBACK", "MED_RECEIVED", "MED_RESOLVED", "WITHDRAWAL_REQUESTED", "WITHDRAWAL_SENT", "WITHDRAWAL_FAILED" ], "description": "Supported webhook event types." }, "CreatePaymentRequest": { "type": "object", "properties": { "productId": { "type": "string", "format": "uuid", "description": "Link this payment to an existing product. If set, `amount` is optional and defaults to the product price." }, "customerId": { "type": "string", "format": "uuid", "description": "Link this payment to an existing customer. For CARD and BOLETO, the linked customer must have name and CPF/CNPJ." }, "amount": { "type": "number", "minimum": 0.01, "maximum": 1000000, "description": "Payment amount. Required unless `productId` is provided." }, "methods": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentMethod" }, "minItems": 1, "default": [ "PIX" ], "description": "Accepted payment methods. Headless payments must use exactly one method." }, "currency": { "$ref": "#/components/schemas/Currency", "default": "BRL" }, "mode": { "type": "string", "enum": [ "hosted", "headless" ], "default": "headless", "description": "hosted redirects the payer to a YuvexPay checkout page. headless returns method data directly for a single payment method. Headless CARD requires the card payload for direct credit card capture. Hosted or multi-method CARD flows continue through checkout/provider invoice URLs, where debit remains available." }, "returnUrl": { "type": "string", "format": "uri", "description": "URL to redirect the payer after payment (hosted mode)." }, "completionUrl": { "type": "string", "format": "uri", "description": "URL to redirect the payer after successful payment completion." }, "description": { "type": "string", "maxLength": 500, "description": "Payment description shown to the payer." }, "externalId": { "type": "string", "maxLength": 100, "description": "Your own reference ID (e.g., order number)." }, "expiresInMinutes": { "type": "integer", "minimum": 5, "maximum": 10080, "default": 60, "description": "Minutes until the payment expires (5-10080, i.e. up to 7 days)." }, "enforcePayerDocument": { "type": "boolean", "default": false, "description": "PIX only. Opt-in request that the charge be paid from an account whose CPF/CNPJ matches the customer's document (same-document payment). Best-effort: when the provider cannot enforce it, the charge is still created and paid normally." }, "customer": { "type": "object", "description": "Inline customer data. For CARD and BOLETO, include at least name and CPF/CNPJ unless you use customerId.", "properties": { "name": { "type": "string", "description": "Payer name. Required for CARD and BOLETO when not using customerId." }, "document": { "type": "string", "description": "CPF or CNPJ. Required for CARD and BOLETO when not using customerId." }, "email": { "type": "string", "format": "email" }, "phone": { "type": "string", "description": "Payer phone number in national or international format." } } }, "metadata": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Arbitrary key-value pairs attached to the payment." }, "passFeeToPayer": { "type": "boolean", "description": "Whether the YuvexPay fee should be added on top of `amount` and charged to the payer instead of being deducted from the merchant's net. When omitted, the company-level `passFeeToPayerDefault` setting applies. Note: payments with a resolved amount below R$1,00 are always charged to the payer regardless of this value (forced passthrough to keep merchant net positive). The final decision is reflected back as `feePassedToPayer` on the Payment object." }, "card": { "type": "object", "description": "Direct credit card charge payload. Allowed only for headless single-method CARD payments and required in that flow.", "properties": { "number": { "type": "string", "description": "Primary account number (PAN), 13-19 digits." }, "expiryMonth": { "type": "string", "description": "Expiration month as 1-2 digits." }, "expiryYear": { "type": "string", "description": "Expiration year as 4 digits." }, "ccv": { "type": "string", "description": "Card security code (3-4 digits)." }, "installments": { "type": "integer", "minimum": 1, "maximum": 12, "default": 1, "description": "Installment count for direct credit card charges." }, "remoteIp": { "type": "string", "description": "Customer IP address required by the acquiring flow." }, "holderInfo": { "type": "object", "description": "Supplemental cardholder billing data. `postalCode` and `addressNumber` are required.", "properties": { "name": { "type": "string" }, "email": { "type": "string", "format": "email" }, "document": { "type": "string", "description": "CPF or CNPJ for the cardholder." }, "postalCode": { "type": "string" }, "addressNumber": { "type": "string" }, "addressComplement": { "type": "string" }, "phone": { "type": "string" }, "mobilePhone": { "type": "string" } }, "required": [ "postalCode", "addressNumber" ] } }, "required": [ "number", "expiryMonth", "expiryYear", "ccv", "remoteIp", "holderInfo" ] }, "boleto": { "type": "object", "description": "Boleto-specific options, applied only when `BOLETO` is one of the `methods`. Fine, interest, and discount mirror the boleto configuration registered with the bank and are settled against the amount the payer actually pays.", "properties": { "dueDate": { "type": "string", "format": "date", "description": "Boleto due date (vencimento) as `YYYY-MM-DD`. Must be today or a future date within one year. Defaults to 3 business days out when omitted. The boleto can still be paid after this date unless the account is configured to reject post-due payment." }, "fine": { "type": "object", "description": "Fine (multa) charged once when the boleto is paid after the due date.", "properties": { "value": { "type": "number", "description": "Fine amount (must be greater than 0), interpreted per `type`." }, "type": { "type": "string", "enum": [ "FIXED", "PERCENTAGE" ], "default": "PERCENTAGE", "description": "Whether `value` is a fixed BRL amount or a percentage of the boleto value." } }, "required": [ "value" ] }, "interest": { "type": "object", "description": "Monthly interest (juros) accrued while the boleto is overdue.", "properties": { "value": { "type": "number", "description": "Monthly interest percentage (must be greater than 0)." } }, "required": [ "value" ] }, "discount": { "type": "object", "description": "Discount granted when the boleto is paid on or before the discount deadline.", "properties": { "value": { "type": "number", "description": "Discount amount (must be greater than 0), interpreted per `type`." }, "type": { "type": "string", "enum": [ "FIXED", "PERCENTAGE" ], "default": "PERCENTAGE", "description": "Whether `value` is a fixed BRL amount or a percentage of the boleto value." }, "dueDateLimitDays": { "type": "integer", "minimum": 0, "maximum": 60, "default": 0, "description": "Number of days before the due date up to which the discount applies. 0 means the discount applies only until the due date." } }, "required": [ "value" ] } } } } }, "RefundPaymentRequest": { "type": "object", "properties": { "amount": { "type": "number", "minimum": 0.01, "description": "Refund amount. Omit for a full refund." }, "reason": { "type": "string", "maxLength": 500, "description": "Reason for the refund." } } }, "CreateWithdrawalRequest": { "type": "object", "required": [ "amount", "destination" ], "properties": { "amount": { "type": "number", "minimum": 10, "maximum": 1000000, "multipleOf": 0.01, "description": "Withdrawal amount (minimum R$10.00)." }, "method": { "type": "string", "enum": [ "PIX" ], "default": "PIX", "description": "Public withdrawals currently support PIX only." }, "currency": { "type": "string", "enum": [ "BRL" ], "default": "BRL" }, "destination": { "description": "Where to send the funds.", "type": "object", "title": "PIX destination", "required": [ "type", "pixKey" ], "properties": { "type": { "type": "string", "enum": [ "pix" ] }, "pixKey": { "type": "string", "minLength": 1, "description": "PIX key. Accepts CPF, CNPJ, e-mail, Brazilian phone (`+55XXXXXXXXXXX`), or a random EVP/UUID. The type is detected automatically; you do not need to send `pixKeyType`. Whitespace and punctuation are stripped server-side." } } }, "description": { "type": "string", "maxLength": 500, "description": "Internal description for this withdrawal." } } }, "CreateProductRequest": { "type": "object", "required": [ "name" ], "properties": { "externalId": { "type": "string", "maxLength": 100, "description": "Your own product ID." }, "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Product name." }, "description": { "type": "string", "maxLength": 1000, "description": "Product description." }, "amount": { "type": "number", "minimum": 0.01, "maximum": 1000000, "description": "Default price." }, "metadata": { "type": "object", "additionalProperties": { "type": "string" } } } }, "UpdateProductRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "description": { "type": "string", "maxLength": 1000 }, "amount": { "type": [ "number", "null" ], "minimum": 0.01, "maximum": 1000000, "description": "Set to `null` to remove the default price." }, "isActive": { "type": "boolean" }, "metadata": { "type": "object", "additionalProperties": { "type": "string" } } } }, "CreateCustomerRequest": { "type": "object", "properties": { "externalId": { "type": "string", "maxLength": 100, "description": "Your own customer ID." }, "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "email": { "type": "string", "format": "email", "maxLength": 255 }, "document": { "type": "string", "maxLength": 20, "description": "CPF or CNPJ number." }, "documentType": { "type": "string", "enum": [ "CPF", "CNPJ" ] }, "phone": { "type": "string", "maxLength": 20 }, "metadata": { "type": "object", "additionalProperties": { "type": "string" } } } }, "UpdateCustomerRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "email": { "type": "string", "format": "email", "maxLength": 255 }, "document": { "type": "string", "maxLength": 20 }, "documentType": { "type": "string", "enum": [ "CPF", "CNPJ" ] }, "phone": { "type": "string", "maxLength": 20 }, "isActive": { "type": "boolean" }, "metadata": { "type": "object", "additionalProperties": { "type": "string" } } } }, "Payment": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "txId": { "type": "string", "description": "YuvexPay transaction ID." }, "amount": { "type": "number", "description": "Merchant-requested base amount, in BRL. This is the seller's intended receivable." }, "feeAmount": { "type": "number", "description": "YuvexPay platform fee, in BRL. When `feePassedToPayer` is true, this equals `payerFeeAmount` and is charged on top of `amount`. When false, this is deducted from `amount` to produce `netAmount`." }, "netAmount": { "type": "number", "description": "Merchant's net receivable, in BRL. Equals `amount` when `feePassedToPayer` is true; equals `amount - feeAmount` otherwise." }, "feePassedToPayer": { "type": "boolean", "description": "Resolved decision (after applying the per-payment override, company default, and sub-R$1 forced passthrough) on whether the fee was added on top for the payer." }, "payerFeeAmount": { "type": "number", "nullable": true, "description": "Fee amount added to the payer's total charge. Null when `feePassedToPayer` is false. When true, payer-charged total = `amount + payerFeeAmount`." }, "status": { "$ref": "#/components/schemas/PaymentStatus" }, "paymentMethod": { "$ref": "#/components/schemas/PaymentMethod" }, "currency": { "$ref": "#/components/schemas/Currency" }, "description": { "type": "string" }, "metadata": { "type": "object", "additionalProperties": { "type": "string" } }, "expiresAt": { "type": "string", "format": "date-time" }, "createdAt": { "type": "string", "format": "date-time" }, "methodData": { "type": "object", "description": "Payment method-specific data (QR code for PIX, barcode for boleto, etc.).", "properties": { "type": { "$ref": "#/components/schemas/PaymentMethod" } }, "additionalProperties": true }, "paidAt": { "type": "string", "format": "date-time", "nullable": true, "description": "Timestamp when the payment was confirmed paid. Null until paid." }, "payer": { "type": "object", "nullable": true, "description": "Payer (debtor) identity captured from the PIX network once the charge is paid. Provider-agnostic. Null for historical records or open-payer charges where no payer data was captured.", "properties": { "name": { "type": "string", "nullable": true, "description": "Payer full name." }, "document": { "type": "string", "nullable": true, "description": "Payer CPF/CNPJ, returned unredacted when the full value is on file. May be masked (e.g. \"75******20\") for open-payer charges where only a masked value was provided by the payer's bank." }, "documentType": { "type": "string", "nullable": true, "enum": ["CPF", "CNPJ"], "description": "Payer document type." }, "institutionName": { "type": "string", "nullable": true, "description": "Payer bank/institution name." }, "institutionIspb": { "type": "string", "nullable": true, "description": "Payer bank ISPB (Banco Central participant identifier)." } } } } }, "Refund": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "txId": { "type": "string" }, "amount": { "type": "number" }, "reason": { "type": "string" }, "status": { "$ref": "#/components/schemas/TransactionStatus" }, "processedAt": { "type": "string", "format": "date-time" }, "createdAt": { "type": "string", "format": "date-time" } } }, "Withdrawal": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "txId": { "type": "string" }, "grossAmount": { "type": "number" }, "feeAmount": { "type": "number" }, "netAmount": { "type": "number" }, "pixKey": { "type": "string", "description": "The destination PIX key, masked. The full key is never returned by the API once the withdrawal is created." }, "pixKeyType": { "type": "string", "description": "Type of PIX key (CPF, CNPJ, EMAIL, PHONE, RANDOM)." }, "status": { "$ref": "#/components/schemas/WithdrawalStatus" }, "isSandbox": { "type": "boolean" }, "createdAt": { "type": "string", "format": "date-time" }, "paymentMethod": { "type": "string", "enum": [ "PIX" ] }, "currency": { "type": "string", "enum": [ "BRL" ] }, "processedAt": { "type": "string", "format": "date-time", "nullable": true }, "errorMessage": { "type": "string", "nullable": true, "description": "Human-readable failure message. Treat as opaque text and surface only to internal operators." } } }, "WithdrawalLimits": { "type": "object", "properties": { "currentLimit": { "type": "number", "description": "Current daily limit in BRL." }, "used": { "type": "number", "description": "Amount already withdrawn today." }, "remaining": { "type": "number", "description": "Remaining withdrawal capacity." }, "isNightTime": { "type": "boolean", "description": "Whether reduced night limits are active." }, "fee": { "type": "number", "description": "Withdrawal fee (flat amount in BRL)." }, "dayStartHour": { "type": "integer", "description": "Hour when daytime limits begin (BRT)." }, "dayEndHour": { "type": "integer", "description": "Hour when nighttime limits begin (BRT)." } } }, "Product": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "description": { "type": "string" }, "amount": { "type": "number" }, "externalId": { "type": "string" }, "isActive": { "type": "boolean" }, "createdAt": { "type": "string", "format": "date-time" } } }, "Customer": { "type": "object", "properties": { "customerId": { "type": "string", "description": "Merchant-facing customer slug (e.g., `cus_ab12cd34ef`). Use this as the `{customerId}` path parameter in subsequent calls." }, "name": { "type": "string" }, "email": { "type": "string" }, "document": { "type": "string" }, "phone": { "type": "string" }, "externalId": { "type": "string" }, "isActive": { "type": "boolean" }, "createdAt": { "type": "string", "format": "date-time" } } }, "CustomerDetail": { "allOf": [ { "$ref": "#/components/schemas/Customer" }, { "type": "object", "properties": { "metadata": { "type": "object", "additionalProperties": { "type": "string" } }, "updatedAt": { "type": "string", "format": "date-time" } } } ] }, "Pagination": { "type": "object", "properties": { "page": { "type": "integer" }, "limit": { "type": "integer" }, "total": { "type": "integer" }, "totalPages": { "type": "integer" } } }, "Error": { "type": "object", "properties": { "error": { "type": "object", "properties": { "code": { "type": "string", "description": "Machine-readable error code." }, "message": { "type": "string", "description": "Human-readable error message." }, "details": { "type": "object", "description": "Additional error context." } } } } }, "WebhookEvent": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique event ID." }, "type": { "$ref": "#/components/schemas/WebhookEventType" }, "data": { "type": "object", "description": "Event payload containing the resource data." } } }, "Balance": { "type": "object", "description": "Account balance for the company associated with the API key. The four buckets `available`, `frozen`, and `held` are independent and additive — `total = available + frozen + held`.", "properties": { "available": { "type": "number", "description": "Amount available for immediate PIX withdrawal, in BRL." }, "frozen": { "type": "number", "description": "Funds reserved/frozen for in-flight withdrawals, refunds, or operational holds. Not currently withdrawable, but still part of the account balance until the underlying operation reaches a terminal state. Independent from `available`." }, "held": { "type": "number", "description": "Confirmed amount pending settlement (for example, card or boleto payments confirmed but not yet liquidated). Will move to `available` once settled." }, "total": { "type": "number", "description": "Total account balance: `available + frozen + held`." }, "currency": { "type": "string", "enum": [ "BRL" ], "description": "Always `BRL`. Multi-currency is not yet supported on the public API." }, "environment": { "type": "string", "enum": [ "SANDBOX", "PRODUCTION" ], "description": "Environment of the API key used to make this call. Sandbox keys always return zeros." }, "updatedAt": { "type": "string", "format": "date-time", "nullable": true, "description": "When the balance row was last updated. `null` if the company has never had any balance activity." } }, "required": [ "available", "frozen", "held", "total", "currency", "environment", "updatedAt" ] }, "ApiKeySelf": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "description": "Internal API key id." }, "name": { "type": "string", "description": "Human-readable name set in the dashboard." }, "description": { "type": "string", "nullable": true }, "environment": { "type": "string", "enum": [ "SANDBOX", "PRODUCTION" ], "description": "Environment the key is bound to." }, "prefix": { "type": "string", "description": "The non-secret prefix of the key (`ypk__`). Safe to log." }, "scopes": { "type": "array", "items": { "type": "string" }, "description": "Permissions granted to the key." }, "ipAllowlist": { "type": "array", "items": { "type": "string" }, "description": "List of allowed IPs/CIDRs. Empty means no restriction." }, "rateLimitPerMinute": { "type": "integer", "nullable": true, "description": "Per-key rate limit in requests per minute, or null for the account default." }, "expiresAt": { "type": "string", "format": "date-time", "nullable": true, "description": "Expiration timestamp, or null if the key does not expire." }, "lastUsedAt": { "type": "string", "format": "date-time", "nullable": true }, "createdAt": { "type": "string", "format": "date-time" } } }, "HeadlessPaymentCreateResponse": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "txId": { "type": "string" }, "amount": { "type": "number", "description": "Merchant-requested base amount. Seller receivable when `feePassedToPayer` is true." }, "feeAmount": { "type": "number", "description": "YuvexPay platform fee." }, "netAmount": { "type": "number", "description": "Merchant's net receivable." }, "feePassedToPayer": { "type": "boolean", "description": "Resolved decision on whether the fee was added on top for the payer." }, "payerFeeAmount": { "type": "number", "nullable": true, "description": "Fee added to payer's total when `feePassedToPayer` is true; null otherwise." }, "isSandbox": { "type": "boolean" }, "status": { "$ref": "#/components/schemas/PaymentStatus" }, "paymentMethod": { "$ref": "#/components/schemas/PaymentMethod" }, "currency": { "$ref": "#/components/schemas/Currency" }, "description": { "type": "string", "nullable": true }, "expiresAt": { "type": "string", "format": "date-time" }, "createdAt": { "type": "string", "format": "date-time" }, "methodData": { "type": "object", "additionalProperties": true, "properties": { "type": { "$ref": "#/components/schemas/PaymentMethod" } }, "description": "Method-specific data. PIX returns QR data. Direct CARD returns captureType: DIRECT plus masked credit card data. Invoice-style CARD/BOLETO returns provider invoice links.", "example": { "type": "CARD", "captureType": "DIRECT", "cardSubtype": "CREDIT", "brand": "VISA", "last4Digits": "1111", "installments": 1 } } } }, "HostedPaymentCreateResponse": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "txId": { "type": "string" }, "amount": { "type": "number", "description": "Merchant-requested base amount. Seller receivable when `feePassedToPayer` is true." }, "feeAmount": { "type": "number", "description": "YuvexPay platform fee." }, "netAmount": { "type": "number", "description": "Merchant's net receivable." }, "feePassedToPayer": { "type": "boolean", "description": "Resolved decision on whether the fee was added on top for the payer." }, "payerFeeAmount": { "type": "number", "nullable": true, "description": "Fee added to payer's total when `feePassedToPayer` is true; null otherwise." }, "status": { "$ref": "#/components/schemas/PaymentStatus" }, "methods": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentMethod" } }, "currency": { "$ref": "#/components/schemas/Currency" }, "checkoutUrl": { "type": "string", "format": "uri" }, "expiresAt": { "type": "string", "format": "date-time" }, "isSandbox": { "type": "boolean" }, "createdAt": { "type": "string", "format": "date-time" } } }, "CreatePaymentResponse": { "type": "object", "properties": { "payment": { "oneOf": [ { "$ref": "#/components/schemas/HeadlessPaymentCreateResponse" }, { "$ref": "#/components/schemas/HostedPaymentCreateResponse" } ] } }, "required": [ "payment" ] } }, "responses": { "ValidationError": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": { "code": "VALIDATION_ERROR", "message": "Invalid request body", "details": { "amount": "Must be greater than 0.01" } } } } } }, "Unauthorized": { "description": "Missing or invalid authentication token.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": { "code": "INVALID_API_KEY", "message": "Invalid or revoked API key" } } } } }, "Forbidden": { "description": "The API key is valid but does not have the required scope for this endpoint.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": { "code": "INSUFFICIENT_SCOPE", "message": "Required scope missing: balance:read" } } } } }, "NotFound": { "description": "Resource not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": { "code": "NOT_FOUND", "message": "Resource not found" } } } } }, "IdempotencyConflict": { "description": "Idempotency conflict. The key was already used with a different payload.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": { "code": "IDEMPOTENCY_PAYLOAD_MISMATCH", "message": "Idempotency key already used with a different request body" } } } } }, "RateLimited": { "description": "Rate limit exceeded.", "headers": { "X-RateLimit-Limit": { "schema": { "type": "integer" }, "description": "Request limit per window." }, "X-RateLimit-Remaining": { "schema": { "type": "integer" }, "description": "Remaining requests in window." }, "X-RateLimit-Reset": { "schema": { "type": "integer" }, "description": "Seconds until the window resets." } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests" } } } } } } } }