{
  "openapi": "3.1.0",
  "info": {
    "title": "Lunium — liquidación cripto ⇄ PIX (Brasil)",
    "version": "1.45.0",
    "summary": "Liquidación entre criptomonedas y PIX en Brasil.",
    "x-lunium-partners": {
      "name": "Lunium Partners — comunidad oficial de integradores",
      "url": "https://t.me/+FerOZMRRP_g5MDk5",
      "description": "Avisos operativos, cambios del contrato e intercambio entre socios. Nunca publiques una clave de API en el grupo."
    },
    "description": "API Lunium: cobros PIX, custodia BRL, entrega de cripto, conversión de cripto externa a PIX y payouts PIX financiados con saldo. Para custodia, envía destino=saldo explícitamente; el valor predeterminado del cobro HTTP sigue siendo cripto. La custodia no requiere una billetera de liquidación fija. La disponibilidad de activos/redes, tarifas, límites y retenciones es dinámica: lee los endpoints adecuados de clave, saldo, catálogo y vista previa. La finalización del pago, la liquidación y el saldo disponible son estados distintos. Los campos de comprobante/E2E se proporcionan para PIX cuando están disponibles, no para toda transacción de cripto. Envía X-API-Key. Usa un external_id estable y un payload sin cambios en los reintentos. Verificación pública de pagos: GET /v1/verificar/{e2e}. El sandbox simula cash-in, custodia, retiros de cripto, payouts PIX, transferencias internas y cash-out. Confirma los PIX de prueba que no admiten pago mediante POST /sandbox/cashin/{cashin_id}/pay. No se realiza ninguna transacción bancaria, de exchange ni de blockchain. Consulta https://docs.luniumpay.com/sandbox . Los errores incluyen erro/acao/detail y request_id/agent_guidance cuando están disponibles; admite campos, eventos y códigos de error desconocidos. MCP: https://api.luniumpay.com/mcp (descubre con tools/list). Manual: https://docs.luniumpay.com/manual · Inglés: https://docs.luniumpay.com/en/manual. Este parche corrige la documentación para ajustarla al comportamiento publicado; los campos de las solicitudes financieras no cambian. Incorporación con IA: https://docs.luniumpay.com/integrar-com-ia . MCP público solo para pruebas: https://api.luniumpay.com/mcp/onboarding . Plan de integración legible por máquina: https://docs.luniumpay.com/integration.json . Política del 15/10/2026: el depósito en saldo cuesta R$ 1,00, sin porcentaje ni comisión. La compra directa cuesta 3,3% + R$ 1,00; la conversión de saldo a cripto cuesta 3,3%, sin una nueva parte fija; el retiro Pix del saldo cuesta 1,5%. La comisión del socio se añade a las tarifas de compra y salida. Cotización de referencia: ask de Binance, sin recargo. Los costes de red y procesamiento, cuando correspondan, aparecen en la vista previa.",
    "contact": {
      "name": "Lunium",
      "email": "contato@luniumpay.com",
      "url": "https://luniumpay.com/integrar?utm_source=openapi&utm_medium=spec"
    },
    "x-documentation-revision": "2026-09-17.4"
  },
  "servers": [
    {
      "url": "https://api.luniumpay.com",
      "description": "Producción"
    }
  ],
  "tags": [
    {
      "name": "Cash-out",
      "description": "Entra cripto, sale PIX."
    },
    {
      "name": "Cash-in",
      "description": "Entra PIX, sale cripto."
    },
    {
      "name": "Catálogo",
      "description": "Lo que se puede liquidar ahora. Fuente de verdad: léelo aquí en lugar de fijar una lista."
    },
    {
      "name": "Verificación",
      "description": "Confirmar un PIX sin ser cliente ni tener clave."
    },
    {
      "name": "Cuenta",
      "description": "Clave, límites y uso."
    },
    {
      "name": "Mesh · Descubrimiento",
      "description": "Cómo un agente descubre Lunium y qué hace, sin hablar con nadie."
    },
    {
      "name": "Mesh · Identidad",
      "description": "Registro de un agente, credenciales y ciclo de vida hasta producción."
    },
    {
      "name": "Mesh · Políticas",
      "description": "Mandate y configuración de liquidación del propio agente."
    },
    {
      "name": "Mesh · Red",
      "description": "Linaje demostrado, grafo de recomendaciones y volumen de la red."
    },
    {
      "name": "Mesh · Economía",
      "description": "0,10 % sobre el volumen liquidado de quienes incorporaste. Nada por registro."
    },
    {
      "name": "Contacto",
      "description": "Derivación a una persona para precios por volumen, contratos, colaboraciones o casos no cubiertos por la documentación."
    },
    {
      "name": "Comisión (sub fee)",
      "description": "La comisión que un socio añade a la tarifa de Lunium, pagada por su usuario final, y el retiro de esa comisión en cripto."
    },
    {
      "name": "Entorno de pruebas",
      "description": "Recorridos financieros ficticios y controles deterministas de simulación."
    },
    {
      "name": "Billetera USDT",
      "description": "Saldo en USDT de tu proyecto: depósito de USDT o USDC en varias redes y Pix pagado con ese saldo (mediante clave Pix o Copia y Pega). La clave `lun_test_` usa el simulador: mismas rutas, estructuras y estados, nada real."
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Clave creada en `POST /keys`. Aparece una sola vez: guárdala al crearla."
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Tu clave. `lun_test_…` es sandbox (no mueve nada); `lun_…` es producción."
      }
    },
    "schemas": {
      "CotacaoSaqueCriptoCarteira": {
        "type": "object",
        "required": [
          "quote_id",
          "funding_source",
          "amount",
          "usdt_total",
          "asset",
          "network",
          "address",
          "minimum_received",
          "amount_estimated",
          "expires_at",
          "sandbox"
        ],
        "properties": {
          "funding_source": {
            "type": "string",
            "enum": [
              "crypto_usdt"
            ]
          },
          "amount": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "asset": {
            "type": "string",
            "enum": [
              "USDT",
              "USDC"
            ]
          },
          "network": {
            "type": "string",
            "enum": [
              "polygon",
              "bsc",
              "tron",
              "eth",
              "arbitrum",
              "optimism",
              "base",
              "avalanche",
              "solana"
            ]
          },
          "address": {
            "type": "string"
          },
          "quote_id": {
            "type": "string",
            "pattern": "^uq_[a-f0-9]{24}$"
          },
          "usdt_total": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "amount_estimated": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "minimum_received": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "network_fee": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "conversion_fee_estimated": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "fee_mode": {
            "type": "string",
            "enum": [
              "deducted"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "sandbox": {
            "type": "boolean"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "SaqueCriptoCarteira": {
        "type": "object",
        "required": [
          "withdrawal_id",
          "external_id",
          "quote_id",
          "funding_source",
          "amount",
          "asset",
          "network",
          "address",
          "status",
          "final",
          "sandbox"
        ],
        "properties": {
          "funding_source": {
            "type": "string",
            "enum": [
              "crypto_usdt"
            ]
          },
          "amount": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "asset": {
            "type": "string",
            "enum": [
              "USDT",
              "USDC"
            ]
          },
          "network": {
            "type": "string",
            "enum": [
              "polygon",
              "bsc",
              "tron",
              "eth",
              "arbitrum",
              "optimism",
              "base",
              "avalanche",
              "solana"
            ]
          },
          "address": {
            "type": "string"
          },
          "quote_id": {
            "type": "string",
            "pattern": "^uq_[a-f0-9]{24}$"
          },
          "withdrawal_id": {
            "type": "string"
          },
          "external_id": {
            "type": "string"
          },
          "network_name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "reserved",
              "funding",
              "converting",
              "processing",
              "under_review",
              "completed",
              "failed"
            ]
          },
          "final": {
            "type": "boolean"
          },
          "amount_estimated": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "minimum_received": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "amount_received": {
            "type": [
              "string",
              "null"
            ]
          },
          "network_fee": {
            "type": [
              "string",
              "null"
            ]
          },
          "usdt_reserved": {
            "type": "string",
            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
          },
          "usdt_debited": {
            "type": [
              "string",
              "null"
            ]
          },
          "tx_hash": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "sandbox": {
            "type": "boolean"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "duplicate_prevented": {
            "type": "boolean"
          },
          "requested_external_id": {
            "type": "string"
          }
        }
      },
      "Erro": {
        "type": "object",
        "description": "Error de la API; los campos pueden variar según la ruta, incluidas las respuestas de infraestructura. Combina el código HTTP con erro y acao cuando estén presentes; detail es para mostrarlo, no para decidir. Admite códigos nuevos.",
        "properties": {
          "erro": {
            "type": "string",
            "description": "Código estable de error. Decide la lógica según él, nunca según el texto de detail. Esta lista se genera a partir de los códigos que realmente emite la API.",
            "x-known-values": [
              "amount_invalido",
              "asset_invalido",
              "br_code_indisponivel",
              "br_code_invalido",
              "br_code_sem_valor",
              "brl_amount_invalido",
              "campos_conflitantes",
              "campos_obrigatorios",
              "carencia_primeiro_deposito",
              "carteira_indisponivel",
              "carteira_nao_liberada",
              "cashin_indisponivel",
              "cashout_indisponivel",
              "catalogo_indisponivel",
              "chave_ausente",
              "chave_desconhecida",
              "chave_incorreta",
              "chave_nao_encontrada",
              "chave_obrigatoria",
              "conflito",
              "consulta_indisponivel",
              "corpo_grande_demais",
              "cotacao_divergente",
              "cotacao_expirada",
              "cotacao_indisponivel",
              "cotacao_recusada",
              "custodia_desligada",
              "deposit_obrigatorio",
              "destino_invalido",
              "devolucao_indisponivel",
              "documento_invalido",
              "em_processamento",
              "email_invalido",
              "email_obrigatorio",
              "endpoint_nao_respondeu",
              "erro_interno",
              "external_id_divergente",
              "formato_invalido",
              "funding_source_invalido",
              "ja_entregue",
              "limite_consultas",
              "limite_de_chaves_teste",
              "limite_diario",
              "limite_diario_recebedor",
              "limite_do_pagador",
              "limite_indisponivel",
              "liquidante_indisponivel",
              "mandate_contraparte_nao_autorizada",
              "mandate_valor_acima_do_teto",
              "memo_obrigatorio",
              "metodo_nao_permitido",
              "muitas_tentativas",
              "muitos_pedidos_abertos",
              "nao_autenticado",
              "nao_encontrado",
              "nao_permitido",
              "nao_processavel",
              "origem_igual_destino",
              "outcome_invalido",
              "pagador_bloqueado",
              "pagador_recusado_pelo_provedor",
              "pagamentos_indisponiveis",
              "payer_tax_invalido",
              "payer_tax_number_invalido",
              "payout_address_invalido",
              "payout_address_obrigatorio",
              "payout_nao_liberado",
              "payout_recusado",
              "pix_key_invalida",
              "pix_key_obrigatoria",
              "provedor_indisponivel",
              "provedor_sem_resposta",
              "rate_limit",
              "rede_indisponivel",
              "refund_address_imutavel",
              "refund_address_invalida",
              "requisicao_invalida",
              "saldo_insuficiente",
              "sandbox_sem_cashin",
              "sandbox_sem_saldo",
              "sandbox_sem_saque",
              "saque_comissao_diario",
              "saque_indisponivel",
              "status_invalido",
              "tax_number_obrigatorio",
              "taxa_alterada",
              "tempo_esgotado",
              "temporariamente_indisponivel",
              "tipo_ambiguo",
              "valor_abaixo_do_minimo",
              "valor_acima_do_maximo",
              "valor_invalido",
              "webhook_nao_configurado",
              "webhook_url_invalida"
            ]
          },
          "acao": {
            "type": "string",
            "enum": [
              "corrigir",
              "repetir",
              "esperar",
              "parar",
              "falar_com_suporte"
            ],
            "description": "corrigir = la solicitud es incorrecta, repetirla idéntica nunca funciona · repetir = fallo transitorio nuestro, inténtalo de nuevo · esperar = la cuota se renueva, vuelve más tarde · parar = no repitas, habla con nosotros · falar_com_suporte = no repitas en bucle; conserva request_id y external_id y deriva el caso a Lunium (ej.: config_provedor)."
          },
          "detail": {
            "type": "string",
            "description": "Texto para personas. Nunca decidas la lógica según él."
          },
          "limits": {
            "type": "object",
            "description": "Presente en los errores de límite, ya convertido a la moneda de la orden."
          },
          "docs": {
            "type": "string",
            "format": "uri"
          },
          "request_id": {
            "type": "string",
            "description": "Identificador de esta solicitud. También se devuelve en la cabecera X-Request-ID y es el que debes citar a soporte. Si envías X-Request-ID con el formato [A-Za-z0-9._:-]{8,64}, se conserva de extremo a extremo.",
            "examples": [
              "req_62f05f21b3794830a241"
            ]
          },
          "code": {
            "type": "string",
            "deprecated": true,
            "description": "Alias ANTIGUO de `erro` — RETIRADA: deja de enviarse el 2026-11-09. NO decidas la lógica según él; usa `erro` (canónico). Nunca aparece sin `erro`."
          }
        }
      },
      "CashOut": {
        "type": "object",
        "properties": {
          "cashout_id": {
            "type": "string",
            "description": "Identificador opaco de la orden. En producción puede ser UUID; en sandbox comienza por sbx_. Consérvalo sin convertirlo."
          },
          "state": {
            "type": "string",
            "enum": [
              "QUOTE_CREATED",
              "AWAITING_DEPOSIT",
              "DEPOSIT_DETECTED",
              "DEPOSIT_CONFIRMED",
              "SELLING",
              "SOLD",
              "FORWARDING",
              "PAYING_OUT",
              "COMPLETED",
              "MANUAL_REVIEW",
              "REFUNDING_CRYPTO",
              "REFUNDED",
              "EXPIRED",
              "FAILED",
              "DELAYED",
              "AWAITING_REFUND_ADDRESS",
              "PROCESSING",
              "REFUNDING"
            ],
            "description": "Estado de la orden. COMPLETED confirma el PIX. Las etapas intermedias varían según la vía. DELAYED pertenece al escenario de sandbox. AWAITING_REFUND_ADDRESS: la orden requiere una devolución y no tiene billetera de retorno; indícala en POST /cash-outs/{cashout_id}/refund-address (venta de cripto y, desde la 1.44.0, venta de DePix). Venta de DePix: QUOTE_CREATED → AWAITING_DEPOSIT → DEPOSIT_DETECTED → PROCESSING → COMPLETED; si no se puede pagar el Pix, REFUNDING → REFUNDED, o AWAITING_REFUND_ADDRESS cuando falta la billetera. El DePix ya transferido al proveedor solo se devuelve después de confirmar el retorno: hasta entonces, la orden permanece en MANUAL_REVIEW y la devolución es como máximo lo que regresó."
          },
          "path": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "FAST",
              "DEX",
              "CONVERT",
              null,
              "depix_liquid"
            ],
            "description": "Vía FAST, DEX o CONVERT. Los plazos dependen de la ruta, las confirmaciones y el procesamiento. DePix/Liquid usa depix_liquid."
          },
          "asset": {
            "type": "string",
            "examples": [
              "USDT"
            ],
            "description": "Activo vendido. Usa el id EXACTO de GET /catalog (ej.: \"usdt\"). Combínalo con network: el par (asset, network) debe existir en el catálogo."
          },
          "network": {
            "type": "string",
            "examples": [
              "polygon"
            ],
            "description": "Red blockchain del depósito, tal como aparece en el catálogo (ej.: \"polygon\"). La dirección de depósito devuelta solo es válida en esta red."
          },
          "amount": {
            "type": "string",
            "description": "Cantidad de cripto, en cadena decimal. Nunca float."
          },
          "brl_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "Importe en reales brasileños (BRL) que recibirá la clave PIX. (es) Reales brasileños que recibirá la clave PIX."
          },
          "pix_key": {
            "type": "string",
            "description": "Clave PIX enmascarada del destinatario en la respuesta. La entrada acepta la clave completa; no compares literalmente la respuesta enmascarada con la entrada."
          },
          "pix_key_type": {
            "type": "string",
            "enum": [
              "cpf",
              "cnpj",
              "phone",
              "email",
              "random"
            ],
            "description": "Normalmente, omítelo: el tipo se deduce de la clave para correos electrónicos, CNPJs, claves aleatorias y teléfonos escritos con el código de país +55. Solo es obligatorio cuando la clave contiene 11 dígitos sin formato, porque un CPF y un teléfono tienen la misma longitud y adivinar podría pagar a la persona equivocada. Un tipo explícito siempre prevalece sobre la deducción."
          },
          "deposit_address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Adonde el cliente envía la cripto. Solo existe después de accept. En sandbox, DePix es un marcador que no admite pagos SANDBOX:LIQUID:NAO_ENVIAR:...; no envíes monedas."
          },
          "deposit_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "Memo/tag que debe acompañar al depósito cuando lo devuelve la aceptación. Usa solo las redes presentes en GET /catalog."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador persistente por intención, de hasta 64 caracteres. Repetir el mismo cuerpo reutiliza la orden. Cambiar la red, activo, token, destino, tipo PIX, importe o billetera de retorno genera un conflicto 409; recupera la original antes de decidir una operación nueva. Las órdenes antiguas sin identidad verificable pueden exigir recuperación por cashout_id/external_id.",
            "maxLength": 64
          },
          "refund_address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Billetera de retorno confirmada por el cliente. Su ausencia no autoriza a usar deposit_from; la orden puede solicitar una dirección en AWAITING_REFUND_ADDRESS. También se aplica a la venta de DePix (dirección Liquid lq1…) desde la 1.44.0."
          },
          "refund_tx_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hash de la devolución cuando se completa; no implica un importe/plazo fijo de reversión para todos los casos."
          },
          "deposit_from": {
            "type": [
              "string",
              "null"
            ],
            "description": "Origen on-chain del depósito, solo informativo. Puede ser una billetera compartida de un exchange; nunca lo elijas automáticamente como destino de devolución."
          },
          "br_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Código Copia y Pega indicado al cotizar (solicitud de cobro), cuando exista. brl_amount es el importe del QR. (es) Cadena de copia y pega indicada al cotizar (solicitud de cobro), si existe. brl_amount es el importe del QR."
          },
          "merchant_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nombre del destinatario leído del QR (solicitud de cobro). (es) Nombre del destinatario leído del QR (solicitud de cobro)."
          },
          "copia_e_cola_buffer_usd": {
            "type": [
              "string",
              "null"
            ],
            "description": "Equivalente en USDT de la reserva operativa de R$1, convertido al cotizar y ya incluido en el total; no lo sumes de nuevo. Las órdenes antiguas conservan su valor original. / Equivalente en USDT de la reserva operativa de BRL 1, convertido al cotizar y ya incluido en el total; no lo añadas de nuevo. Las órdenes existentes conservan su valor original.",
            "example": "0.200000"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Instante en que caduca la cotización, ISO 8601 en UTC (ej.: 2026-09-02T14:03:00Z). Las aceptaciones posteriores fallan con erro=cotacao_expirada: vuelve a cotizar en lugar de insistir."
          },
          "pix_e2e": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador de extremo a extremo del Banco Central del PIX completado. Cualquiera puede verificarlo en GET /v1/verificar/{e2e}, sin clave. (es) Identificador oficial del PIX en el Banco Central. Es la prueba: entrégala a tu cliente final. En sandbox es ficticio, con ISPB 00000000; no acredita un pago bancario.",
            "examples": [
              "E37293930202607312006361894c4a82"
            ]
          },
          "pix_paid_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "receipt_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Página compartible del comprobante, cuando esté lista. Puede seguir siendo null en el evento cashout.completed; cashout.receipt_ready y la consulta de la misma orden proporcionan el enlace después.",
            "examples": [
              "https://app.luniumpay.com/comprovante/uwscff6ASNS1oUcH2LHbvw"
            ]
          },
          "receipt_pdf_url": {
            "type": [
              "string",
              "null"
            ],
            "nullable": true,
            "format": "uri",
            "description": "Comprobante como ARCHIVO PDF: adjúntalo a una consulta de soporte, envíalo por WhatsApp y guárdalo para la contabilidad. No depende de que nuestra página esté disponible el día de la comprobación. Incluye nombre, documento fiscal e institución del destinatario, importe, fecha, E2E y enlace de verificación. (es) Comprobante en ARCHIVO PDF. Es lo que se adjunta a una consulta de soporte, se envía por WhatsApp al cliente final y se conserva en la contabilidad; no depende de que la página esté disponible el día de la revisión. Incluye nombre, documento e institución del destinatario, importe, fecha, E2E y enlace de verificación. Se genera a partir de la MISMA fuente de datos de la página: ambos nunca difieren. Es `null` mientras la orden no haya alcanzado el estado que lo completa. Comprobante oficial: qué contiene y por dónde llega (API, webhook, panel del socio, Telegram): https://docs.luniumpay.com/manual#comprovante",
            "example": "https://app.luniumpay.com/comprovante/qigpnCTx3gM-Ge7hN27Mvw.pdf"
          },
          "verify_url": {
            "type": [
              "string",
              "null"
            ],
            "nullable": true,
            "format": "uri",
            "description": "Enlace directo a la verificación ABIERTA (sin clave). Entrégalo a tu contraparte para que confirme el pago por sí misma, sin confiar en ti ni en nosotros. Nunca expone la clave PIX, el nombre completo ni el documento fiscal. (es) Enlace directo a la verificación ABIERTA (sin clave). Entrégalo a tu contraparte para que confirme el pago por sí misma, sin tener que confiar en ti ni en nosotros. No expone la clave PIX, el nombre completo ni el documento. Es `null` mientras la orden no haya alcanzado el estado que lo completa.",
            "example": "https://api.luniumpay.com/v1/verificar/E3729393020260731214021222ac6ff1"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "timeline": {
            "type": "array",
            "description": "Línea de tiempo marcada por el SERVIDOR en cada transición (hora del gateway, no de tus consultas periódicas): AWAITING_DEPOSIT → DEPOSIT_DETECTED → DEPOSIT_CONFIRMED → (SELLING → SOLD → FORWARDING, solo en el exchange) → PAYING_OUT → COMPLETED. Úsala para el seguimiento del cliente.",
            "items": {
              "type": "object",
              "properties": {
                "state": {
                  "type": "string"
                },
                "at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "confirmations": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Confirmaciones del depósito ya observadas, EN VIVO. Solo aparece mientras la orden se está confirmando y no se guarda: el número cambia con cada bloque. Úsalo con confirmations_required para mostrar el progreso en lugar de un “esperando” sin fin."
          },
          "confirmations_required": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Confirmaciones que exige el exchange antes de acreditar el depósito de esta red."
          },
          "failure_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Motivo del fallo cuando se devuelve, también en los escenarios de sandbox."
          },
          "sandbox": {
            "type": "boolean",
            "description": "True para operaciones ficticias de sandbox."
          },
          "simulation": {
            "type": "object",
            "additionalProperties": true
          },
          "partner_fee_bps": {
            "type": "integer",
            "nullable": true,
            "description": "Comisión adicional del socio congelada en esta venta (bps); null en las órdenes anteriores al campo o las ventas DePix."
          },
          "partner_fee_brl_cents": {
            "type": "integer",
            "nullable": true,
            "description": "Parte del socio en centavos, fijada al confirmar el PIX; es el importe acreditado en el libro de comisiones."
          },
          "refund_address_required": {
            "type": "boolean",
            "description": "true en AWAITING_REFUND_ADDRESS: consulta los datos de la devolución e indica una billetera confirmada por el cliente en POST /cash-outs/{cashout_id}/refund-address."
          },
          "refund_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cantidad efectiva que se devolverá, cuando esté calculada; no presupongas la cantidad original. Venta de DePix: con todo el DePix en Lunium, refund_amount, refund_asset (DEPIX) y refund_network (liquid) ya se devuelven completados en AWAITING_REFUND_ADDRESS. Si el DePix ya se había transferido al proveedor, estos campos permanecen null en MANUAL_REVIEW hasta confirmar el retorno; después, refund_amount es como máximo lo que regresó (más la parte que no llegó a transferirse, hasta el importe de la orden)."
          },
          "refund_asset": {
            "type": [
              "string",
              "null"
            ],
            "description": "Activo efectivo de la devolución; puede diferir del activo depositado."
          },
          "refund_network": {
            "type": [
              "string",
              "null"
            ],
            "description": "Red efectiva de la devolución; usa una billetera compatible confirmada por el cliente."
          },
          "provider_return_txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Referencia de la devolución del socio a Lunium; no es prueba de una reversión al cliente."
          },
          "fee_bps": {
            "type": "integer",
            "description": "Porcentaje de la venta de DePix en puntos básicos."
          },
          "fee_fixed_cents": {
            "type": "integer",
            "description": "Parte fija de la venta de DePix, en centavos."
          },
          "fee_total_cents": {
            "type": "integer",
            "description": "Tarifa total, en centavos; disponible en la cotización DePix y en la orden simulada."
          },
          "net_cents": {
            "type": "integer",
            "description": "PIX neto, en centavos; disponible en la cotización DePix y en la orden simulada."
          },
          "pix_key_reserve_usd": {
            "type": [
              "string",
              "null"
            ],
            "description": "Equivalente en USDT de la reserva operativa de R$1, convertido al cotizar y ya incluido en el total; no lo sumes de nuevo. Las órdenes antiguas conservan su valor original. / Equivalente en USDT de la reserva operativa de BRL 1, convertido al cotizar y ya incluido en el total; no lo añadas de nuevo. Las órdenes existentes conservan su valor original.",
            "example": "0.200000"
          },
          "reserve_brl": {
            "type": [
              "string",
              "null"
            ],
            "example": "1.00",
            "description": "Reserva operativa fija de R$1 en las órdenes nuevas, ya incluida en el total. Las antiguas conservan la reserva original. / Reserva operativa fija de BRL 1 en las órdenes nuevas, ya incluida en el total; las órdenes existentes conservan su reserva original."
          }
        }
      },
      "EventoWebhook": {
        "type": "object",
        "description": "Cuerpo que enviamos a tu endpoint. Trata los eventos desconocidos como no-op: la lista crece sin aviso e ignorar lo que no reconoces es el comportamiento correcto.",
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "cashin.paid",
              "cashin.delayed",
              "cashin.held",
              "cashin.settled",
              "cashin.settlement_failed",
              "cashin.expired",
              "cashin.refunded",
              "cashin.failed",
              "cashout.awaiting_deposit",
              "cashout.deposit_detected",
              "cashout.confirming",
              "cashout.processing",
              "cashout.under_review",
              "cashout.awaiting_refund_address",
              "cashout.refunding",
              "cashout.completed",
              "cashout.receipt_ready",
              "cashout.refunded",
              "cashout.expired",
              "cashout.failed",
              "payout.sent",
              "payout.failed",
              "payout.refunded",
              "webhook.test",
              "saldo.liberado",
              "saldo.congelado",
              "saldo.transferido",
              "wallet.deposit_credited",
              "wallet.payment_completed",
              "wallet.payment_failed",
              "wallet.withdrawal.completed",
              "wallet.withdrawal.failed"
            ],
            "description": "Decide la lógica según este campo. `cashin.settled` es el evento para acreditar a tu cliente. `cashout.confirming`: progreso del depósito mientras el exchange reúne confirmaciones. Se emite al 25%, 50% y 75%, solo en redes que exigen una espera real (≥120 confirmaciones), con `confirmations` y `confirmations_required` en el payload. Existe porque entre `cashout.deposit_detected` y el final de la espera puede haber media hora de silencio. `cashin.held`: PIX pagado, pero entrega retenida por la política de la clave (no es la retención del proveedor, que aparece como `status: delayed`); `data` incluye `liberar_em`. `cashin.delayed`: PIX pagado, retenido en el proveedor durante 24h (`delay_until`). `cashout.awaiting_refund_address`: la orden requiere una devolución y no tiene billetera de retorno (`state: AWAITING_REFUND_ADDRESS`, `refund_address_required: true`). Pide la billetera a tu cliente y envíala en POST /cash-outs/{cashout_id}/refund-address; Lunium nunca devuelve al origen del depósito. Se aplica a la venta de cripto y, desde la 1.44.0, a la venta de DePix. `data` es la orden, en el mismo formato de GET /cash-outs/{cashout_id}. Billetera USDT: `wallet.deposit_credited` (data: deposit_id, amount_received, asset, network, balance_available, credited_at) · `wallet.payment_completed` (data: payment_id, brl_amount, cashout_id, usdt_debited) · `wallet.payment_failed` (data: payment_id, brl_amount, cashout_id, status, refunded — `refunded: true` = la reserva volvió al saldo). En las pruebas, los mismos eventos llegan con `sandbox: true`."
          },
          "event_id": {
            "type": "string",
            "pattern": "^evt_[0-9a-f]{24}$",
            "description": "Identidad ESTABLE del evento: la misma en todos los reintentos. Guárdala e ignora las repeticiones: es lo que garantiza que no acredites dos veces.",
            "examples": [
              "evt_9c3f21a70b5e4d8812ff0a63"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "description": "Mismo formato que el endpoint de estado de la operación correspondiente."
          }
        },
        "required": [
          "event",
          "created_at",
          "data"
        ]
      },
      "EntregaWebhook": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string"
          },
          "event": {
            "type": "string",
            "enum": [
              "cashin.paid",
              "cashin.delayed",
              "cashin.held",
              "cashin.settled",
              "cashin.settlement_failed",
              "cashin.expired",
              "cashin.refunded",
              "cashin.failed",
              "cashout.awaiting_deposit",
              "cashout.deposit_detected",
              "cashout.confirming",
              "cashout.processing",
              "cashout.under_review",
              "cashout.awaiting_refund_address",
              "cashout.refunding",
              "cashout.completed",
              "cashout.receipt_ready",
              "cashout.refunded",
              "cashout.expired",
              "cashout.failed",
              "payout.sent",
              "payout.failed",
              "payout.refunded",
              "webhook.test",
              "saldo.liberado",
              "saldo.congelado",
              "saldo.transferido",
              "wallet.deposit_credited",
              "wallet.payment_completed",
              "wallet.payment_failed",
              "wallet.withdrawal.completed",
              "wallet.withdrawal.failed"
            ]
          },
          "operation_id": {
            "type": "string",
            "description": "Id de la operación que generó el evento."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "sent",
              "failed"
            ],
            "description": "failed = agotó los 12 intentos. Usa el reintento para recuperarlo."
          },
          "attempts": {
            "type": "integer"
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "next_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TitularPix": {
        "type": "object",
        "required": [
          "pix_key",
          "pix_key_type",
          "owner_name",
          "verified",
          "source",
          "checked_at"
        ],
        "properties": {
          "pix_key": {
            "type": "string",
            "description": "La clave, normalizada (teléfono en +55…)."
          },
          "pix_key_type": {
            "type": "string",
            "enum": [
              "cpf",
              "cnpj",
              "phone",
              "email",
              "random"
            ],
            "description": "Tipo de la clave consultada: \"cpf\", \"cnpj\", \"phone\", \"email\" o \"random\"."
          },
          "owner_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nombre del titular, tal como figura en el DICT.",
            "examples": [
              "João Silva"
            ]
          },
          "owner_tax_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "CPF/CNPJ ENMASCARADO. Nunca se devuelve completo.",
            "examples": [
              "***.202.745-**"
            ]
          },
          "institution_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Institución donde está registrada la clave.",
            "examples": [
              "NU PAGAMENTOS - IP"
            ]
          },
          "ispb": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISPB de la institución (8 dígitos).",
            "examples": [
              "18236120"
            ]
          },
          "verified": {
            "type": "boolean",
            "description": "true cuando se consultó o simuló el titular (source=sandbox); false cuando no se verificó."
          },
          "source": {
            "type": "string",
            "enum": [
              "dict",
              "sandbox",
              "disabled"
            ]
          },
          "checked_at": {
            "type": "string",
            "format": "date-time"
          },
          "cached": {
            "type": "boolean",
            "description": "true cuando la respuesta procede de la caché de 24h."
          },
          "sandbox": {
            "type": "boolean",
            "description": "Solo en claves de prueba: titular ficticio."
          },
          "available": {
            "type": "boolean",
            "description": "false cuando la consulta no está disponible; puede devolverse con HTTP 200."
          },
          "optional": {
            "type": "boolean",
            "description": "La consulta es auxiliar; no es un requisito para pagar."
          },
          "verification_status": {
            "type": "string",
            "description": "not_performed cuando no se realizó la verificación."
          },
          "detail": {
            "type": "string"
          }
        }
      },
      "NextAction": {
        "type": "object",
        "description": "El siguiente paso, en forma de llamada. Un agente nunca debería necesitar interpretar texto humano para continuar.",
        "properties": {
          "method": {
            "type": "string",
            "example": "POST"
          },
          "endpoint": {
            "type": "string",
            "example": "/mesh/agents/{agent_id}/settlement"
          },
          "why": {
            "type": "string",
            "example": "sem rota de liquidacao o dinheiro nao tem para onde ir"
          }
        }
      },
      "ErroAutocorrigivel": {
        "type": "object",
        "description": "Error que el propio agente puede resolver. `acao` es un enum estable: corrigir (tu solicitud es incorrecta), esperar (cuota), parar (repetir no sirve), repetir (fallo transitorio nuestro).",
        "properties": {
          "erro": {
            "type": "string",
            "example": "mandate_valor_acima_do_teto"
          },
          "acao": {
            "type": "string",
            "enum": [
              "corrigir",
              "esperar",
              "parar",
              "repetir"
            ]
          },
          "detail": {
            "type": "string"
          },
          "missing": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "next_actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NextAction"
            }
          }
        },
        "required": [
          "erro",
          "acao"
        ]
      },
      "Capability": {
        "type": "object",
        "description": "Lo que hace Lunium, descrito por ATRIBUTO y no por su nombre interno, para que un agente encuentre su propia intención sin conocer nuestro vocabulario.",
        "properties": {
          "descricao": {
            "type": "string"
          },
          "intent": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "sell_crypto",
              "receive_fiat",
              "offramp",
              "cash_out"
            ]
          },
          "input_assets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "USDT"
            ]
          },
          "input_networks": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "polygon"
            ]
          },
          "output_currencies": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "BRL"
            ]
          },
          "payment_rails": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "PIX"
            ]
          },
          "endpoint": {
            "type": "string",
            "example": "/cash-outs"
          },
          "direction": {
            "type": "string",
            "example": "crypto->fiat"
          },
          "settlement_speed": {
            "type": "string",
            "enum": [
              "seconds",
              "minutes"
            ]
          }
        }
      },
      "MeshDiscovery": {
        "type": "object",
        "description": "Documento único que responde a lo que pregunta un agente antes de integrar. Generado a partir de la configuración activa: no puede diferir de lo que hace la API.",
        "properties": {
          "quem_somos": {
            "type": "object"
          },
          "como_falar_comigo": {
            "type": "object",
            "description": "REST, OpenAPI, MCP, A2A y Mesh."
          },
          "capacidades": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Capability"
            }
          },
          "como_escolher_capacidade": {
            "type": "object",
            "description": "Índice invertido intención -> capacidades, además de cómo filtrar por atributo.",
            "properties": {
              "por_intencao": {
                "type": "object",
                "additionalProperties": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "execucao": {
            "type": "object",
            "description": "Por capacidad: endpoint, campos obligatorios y ejemplo listo para usar."
          },
          "ativos_e_redes": {
            "type": "object"
          },
          "limites": {
            "type": "object"
          },
          "como_comecar": {
            "type": "object"
          },
          "regra_de_seguranca": {
            "type": "object"
          },
          "atribuicao": {
            "type": "object"
          }
        }
      },
      "AgentIdentity": {
        "type": "object",
        "description": "Identidad PERMANENTE del agente. La credencial es sustituible; el linaje, volumen, recompensa, mandate y reputación pertenecen al agent_id.",
        "properties": {
          "agent_id": {
            "type": "string",
            "example": "agt_2319c9da313e84af3b"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "$ref": "#/components/schemas/AgentLifecycle"
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ]
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "settlement_address": {
            "type": [
              "string",
              "null"
            ]
          },
          "referred_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Inmutable después del registro (trigger en la base de datos)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AgentLifecycle": {
        "type": "string",
        "enum": [
          "registered",
          "sandbox_active",
          "validated",
          "production_active",
          "suspended"
        ],
        "description": "Producción se activa por POLÍTICA, sin intervención humana en el proceso. No existe un estado de espera de aprobación: el control de riesgo está en las reglas por PAGADOR (cash-in), en el límite por operación, en el límite diario de quien recibe el PIX (venta) y en el mandate de la propia clave; no existe un límite diario por clave de API (desde el 10/09/2026) ni una cola de aprobación."
      },
      "AgentRegistration": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 80
          },
          "description": {
            "type": "string"
          },
          "contact": {
            "type": "string"
          },
          "agent_card_url": {
            "type": "string"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "referral_token": {
            "type": "string",
            "description": "Atestación firmada por quien recomendó. Es la ÚNICA forma de tener linaje: `referred_by` declarado por el cliente se rechaza, porque tiene valor económico."
          }
        }
      },
      "AgentKey": {
        "type": "object",
        "description": "Credencial. `lun_test_*` = sandbox, `lun_live_*` = producción. Las claves emitidas antes del 29/08/2026 comienzan por `lun_` y siguen siendo válidas: la autenticación se realiza mediante hash, nunca por prefijo; el prefijo es para las personas.",
        "properties": {
          "api_key": {
            "type": "string",
            "example": "lun_live_a977c15a…",
            "description": "Aparece UNA vez. Solo guardamos el hash."
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "Mandate": {
        "type": "object",
        "description": "Política que la propia clave se impone. Solo RESTRINGE los límites, nunca los amplía; por eso el agente puede definirla por sí mismo: lo máximo que hace es limitarse. Obligatoria antes de producción.",
        "properties": {
          "max_por_operacao_cents": {
            "type": "integer",
            "example": 30000
          },
          "max_diario_cents": {
            "type": "integer",
            "example": 200000
          },
          "contrapartes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Claves PIX autorizadas. Vacío = sin restricciones."
          }
        }
      },
      "SettlementConfiguration": {
        "type": "object",
        "required": [
          "settlement_address"
        ],
        "properties": {
          "settlement_address": {
            "type": "string",
            "example": "0x51e3…75e0",
            "description": "Billetera en la red de liquidación compatible."
          }
        }
      },
      "ProductionActivation": {
        "type": "object",
        "description": "Activación AUTOMÁTICA. `activated_by` siempre es `policy`, nunca `operator`.",
        "properties": {
          "status": {
            "type": "string",
            "example": "production_active"
          },
          "agent_id": {
            "type": "string"
          },
          "environment": {
            "type": "string",
            "example": "production"
          },
          "activated_at": {
            "type": "string",
            "format": "date-time"
          },
          "activated_by": {
            "type": "string",
            "example": "policy"
          },
          "api_key": {
            "type": "string",
            "description": "Credencial de producción (`lun_live_*`), una sola vez."
          },
          "settlement": {
            "type": "object"
          },
          "mandate": {
            "$ref": "#/components/schemas/Mandate"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ReferralAttestation": {
        "type": "object",
        "description": "Token firmado (JWS HS256) que DEMUESTRA quién recomendó. Uso único, con vencimiento. Sin él, el agente se incorpora como raíz y nadie recibe remuneración por él.",
        "properties": {
          "type": {
            "type": "string",
            "example": "mesh_referral"
          },
          "referrer_agent_id": {
            "type": "string"
          },
          "referral_token": {
            "type": "string"
          },
          "capability": {
            "type": [
              "string",
              "null"
            ]
          },
          "nonce": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "one_time_use": {
            "type": "boolean",
            "example": true
          }
        }
      },
      "AgentNetwork": {
        "type": "object",
        "description": "El árbol por debajo de un agente. `network_volume` cuenta todo el árbol (sirve para la reputación); `reward_eligible_volume` cuenta solo lo que genera remuneración.",
        "properties": {
          "agent_id": {
            "type": "string"
          },
          "referred_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "depth": {
            "type": "integer"
          },
          "direct_children": {
            "type": "integer"
          },
          "total_descendants": {
            "type": "integer"
          },
          "own_volume_cents": {
            "type": "integer"
          },
          "own_transactions": {
            "type": "integer"
          },
          "network_volume_cents": {
            "type": "integer"
          },
          "network_transactions": {
            "type": "integer"
          },
          "reward_eligible_volume_cents": {
            "type": "integer"
          },
          "lifetime_rewards_cents": {
            "type": "integer"
          },
          "first_operation": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "production_since": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "children": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "MeshEconomyPolicy": {
        "type": "object",
        "description": "Reglas públicas de la economía. SIN LIQUIDACIÓN → SIN RECOMPENSA.",
        "properties": {
          "model": {
            "type": "string",
            "example": "transaction_attribution"
          },
          "direct_rate": {
            "type": "string",
            "example": "0.10%"
          },
          "direct_rate_bps": {
            "type": "integer",
            "example": 10
          },
          "max_paid_levels": {
            "type": "integer",
            "example": 1
          },
          "recruitment_reward": {
            "type": "boolean",
            "example": false
          },
          "requires_settled_transaction": {
            "type": "boolean",
            "example": true
          },
          "revenue_share_cap": {
            "type": "string"
          }
        }
      },
      "RewardEvent": {
        "type": "object",
        "description": "Asiento del ledger. Inmutable: una reversión es un asiento NEGATIVO nuevo, nunca UPDATE ni DELETE.",
        "properties": {
          "transaction_id": {
            "type": "string"
          },
          "transaction_kind": {
            "type": "string",
            "enum": [
              "cashout",
              "cashin"
            ]
          },
          "source_agent_id": {
            "type": "string",
            "description": "Quién generó el volumen."
          },
          "referral_level": {
            "type": "integer",
            "example": 1
          },
          "volume_cents": {
            "type": "integer"
          },
          "rate_bps": {
            "type": "integer",
            "example": 10
          },
          "gross_reward_cents": {
            "type": "integer"
          },
          "revenue_cents": {
            "type": "integer",
            "description": "Ingresos de Lunium en la operación."
          },
          "revenue_cap_cents": {
            "type": "integer",
            "description": "Límite aplicable a la recompensa."
          },
          "final_reward_cents": {
            "type": "integer",
            "description": "Negativo cuando es una reversión."
          },
          "reward_usdt": {
            "type": [
              "number",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "available",
              "paid",
              "reversed"
            ]
          },
          "motivo": {
            "type": [
              "string",
              "null"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RewardBalance": {
        "type": "object",
        "description": "Saldo del agent_id, nunca de la credencial. Rotar la clave no hace perder saldo.",
        "properties": {
          "agent_id": {
            "type": "string"
          },
          "own_volume_cents": {
            "type": "integer"
          },
          "direct_referral_volume_cents": {
            "type": "integer"
          },
          "network_volume_cents": {
            "type": "integer"
          },
          "pending_rewards_cents": {
            "type": "integer"
          },
          "available_rewards_cents": {
            "type": "integer"
          },
          "paid_rewards_cents": {
            "type": "integer"
          },
          "lifetime_rewards_cents": {
            "type": "integer"
          },
          "reward_events": {
            "type": "integer"
          },
          "reversals": {
            "type": "integer"
          },
          "policy": {
            "$ref": "#/components/schemas/MeshEconomyPolicy"
          },
          "ledger": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RewardEvent"
            }
          }
        }
      },
      "ServiceRecommendation": {
        "type": "object",
        "description": "Lo que un agente entrega a otro. NO incluye claves, endpoints privados ni esquemas: solo el dominio, la capacidad y (opcionalmente) la atestación. Quien lo recibe sigue obligado a verificar Lunium por su cuenta.",
        "properties": {
          "type": {
            "type": "string",
            "example": "service_recommendation"
          },
          "from_agent": {
            "type": "string"
          },
          "domain": {
            "type": "string",
            "example": "https://luniumpay.com"
          },
          "capability": {
            "type": "string",
            "example": "usdt_to_pix"
          },
          "referral_token": {
            "type": "string"
          },
          "verify_yourself": {
            "type": "string"
          }
        }
      },
      "Cobranca": {
        "type": "object",
        "description": "Respuesta de creación de la solicitud de cobro, con QR. Para estado/lista/webhook, consulta StatusCobranca.",
        "properties": {
          "cashin_id": {
            "type": "string",
            "description": "Identificador de la solicitud de cobro (ci_…)."
          },
          "status": {
            "type": "string",
            "description": "Estado del PIX. paid no acredita por sí solo el crédito/entrega; lee settlement_status.",
            "enum": [
              "pending",
              "delayed",
              "under_review",
              "paid",
              "expired",
              "refunded",
              "failed"
            ]
          },
          "amount_cents": {
            "type": "integer",
            "description": "Importe del PIX en centavos."
          },
          "destino": {
            "type": "string",
            "description": "cripto (entrega on-chain) o saldo (acredita la custodia BRL de la clave, utilizable en POST /payouts y POST /saldo/sacar-cripto).",
            "enum": [
              "cripto",
              "saldo"
            ]
          },
          "fonte": {
            "type": "string",
            "enum": [
              "pix",
              "saldo"
            ],
            "description": "Origen del importe al crear: PIX o retiro del saldo."
          },
          "customer_ref": {
            "type": [
              "string",
              "null"
            ],
            "description": "Tu referencia del cliente final (subcuenta en el saldo).",
            "maxLength": 80
          },
          "payout_address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Billetera que recibe la cripto (destino=cripto)."
          },
          "payout_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "Memo/tag de la billetera de destino en redes colectivas (destino=cripto)."
          },
          "chain": {
            "type": "string",
            "description": "Red de entrega (id de GET /cashin/catalog)."
          },
          "asset": {
            "type": "string",
            "description": "Activo entregado (usdt, usdc, btc, …)."
          },
          "lunium_fee_bps": {
            "type": "integer",
            "description": "Tarifa porcentual congelada en la solicitud de cobro, en bps."
          },
          "lunium_fee_fixed_cents": {
            "type": "integer",
            "description": "Parte fija congelada en la solicitud de cobro, en centavos."
          },
          "partner_fee_bps": {
            "type": "integer",
            "description": "Comisión adicional congelada en la solicitud de cobro."
          },
          "qr_copypaste": {
            "type": [
              "string",
              "null"
            ],
            "description": "PIX Copia y Pega al crear; null en el retiro de custodia."
          },
          "qr_image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Imagen del QR (PNG): solo en la respuesta de creación."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado.",
            "maxLength": 64
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Validez de la propia solicitud de cobro; lee este timestamp, también para la validez ampliada por el bot."
          },
          "delay_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Instante de liberación indicado para la retención del proveedor, cuando esté disponible."
          },
          "liberar_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Cuándo el crédito en saldo sale del período de espera. null cuando ya entra disponible (predeterminado desde el 16/09/2026)."
          },
          "hold_hours": {
            "type": "integer",
            "description": "Retención local de la solicitud de cobro en horas. No es un alias de held_hours ni del período de espera general del saldo."
          },
          "held_hours": {
            "type": "integer",
            "description": "Retención solicitada al proveedor. Puede ser cero mientras existe una retención local (hold_hours/liberar_em)."
          },
          "held": {
            "type": "boolean",
            "description": "true cuando held_hours > 0. Por sí solo no revela la retención local."
          },
          "sandbox": {
            "type": "boolean",
            "description": "True para operaciones ficticias de sandbox."
          },
          "simulation": {
            "type": "object",
            "additionalProperties": true
          },
          "sandbox_payment": {
            "type": "object",
            "properties": {
              "method": {
                "const": "POST"
              },
              "path": {
                "type": "string"
              }
            }
          },
          "timeline": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "delivery_mode": {
            "type": "string",
            "enum": [
              "full",
              "split"
            ],
            "description": "Solo en chain=\"liquid\": cómo se entregó el DePix. Ausente en las demás redes."
          },
          "net_cents": {
            "type": "integer",
            "description": "Solo en chain=\"liquid\" con delivery_mode=\"split\": cuánto recibe el destinatario en DePix, ya sin la tarifa. Es este importe el que Lunium envía on-chain."
          },
          "fee_total_cents": {
            "type": "integer",
            "description": "Solo en chain=\"liquid\" con delivery_mode=\"split\": todo lo descontado del bruto (tarifa fija + porcentaje). net_cents + fee_total_cents == amount_cents."
          }
        }
      },
      "StatusCobranca": {
        "type": "object",
        "description": "Estado de la solicitud de cobro; GET puede añadir la vía, timeline y tempos_tipicos. La lista y el webhook usan el objeto base.",
        "properties": {
          "cashin_id": {
            "type": "string",
            "description": "Identificador de la solicitud de cobro (ci_…)."
          },
          "status": {
            "type": "string",
            "description": "Estado del PIX. paid no acredita por sí solo el crédito/entrega; lee settlement_status.",
            "enum": [
              "pending",
              "delayed",
              "under_review",
              "paid",
              "expired",
              "refunded",
              "failed"
            ]
          },
          "settlement_status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Estado del crédito/entrega: sent completado; incerto requiere conciliación. PIX pagado y entrega son estados distintos.",
            "enum": [
              "pending",
              "sending",
              "entregando",
              "sent",
              "incerto",
              "failed",
              null
            ]
          },
          "amount_cents": {
            "type": "integer",
            "description": "Importe del PIX en centavos."
          },
          "depix_received_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Importe recibido del liquidador antes de descontar las tarifas de depósito de la clave; no es el crédito neto de custodia."
          },
          "usdt_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "Campo antiguo de cantidad devuelto por la liquidación; interprétalo junto con asset y los campos específicos de la ruta."
          },
          "settlement_tx_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hash on-chain de la entrega (o id interno cuando la entrega se realiza mediante el exchange)."
          },
          "settlement_tx_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Enlace del explorador para el hash anterior, cuando existe."
          },
          "payout_address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Billetera que recibe la cripto (destino=cripto)."
          },
          "payout_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "Memo/tag de la billetera de destino en redes colectivas (destino=cripto)."
          },
          "chain": {
            "type": "string",
            "description": "Red de entrega (id de GET /cashin/catalog)."
          },
          "asset": {
            "type": "string",
            "description": "Activo entregado (usdt, usdc, btc, …)."
          },
          "payer_tax_number": {
            "type": "string",
            "description": "CPF/CNPJ del pagador: quien debe pagar el QR. El PIX de otro documento se devuelve (refund_reason PAYER_MISMATCH)."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado.",
            "maxLength": 64
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Validez de la propia solicitud de cobro; lee este timestamp, también para la validez ampliada por el bot."
          },
          "paid_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "settled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "destino": {
            "type": "string",
            "description": "cripto (entrega on-chain) o saldo (acredita la custodia BRL de la clave, utilizable en POST /payouts y POST /saldo/sacar-cripto).",
            "enum": [
              "cripto",
              "saldo"
            ]
          },
          "held_hours": {
            "type": "integer",
            "description": "Retención solicitada al proveedor. Puede ser cero mientras existe una retención local (hold_hours/liberar_em)."
          },
          "held": {
            "type": "boolean",
            "description": "true cuando held_hours > 0. Por sí solo no revela la retención local."
          },
          "delay_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Instante de liberación indicado para la retención del proveedor, cuando esté disponible."
          },
          "liberar_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Cuándo el crédito en saldo sale del período de espera. null cuando ya entra disponible (predeterminado desde el 16/09/2026)."
          },
          "e2e": {
            "type": [
              "string",
              "null"
            ],
            "description": "EndToEndId del PIX recibido (Banco Central)."
          },
          "payer_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nombre del pagador cuando lo proporciona o lo identifica el banco."
          },
          "customer_ref": {
            "type": [
              "string",
              "null"
            ],
            "description": "Tu referencia del cliente final (subcuenta en el saldo).",
            "maxLength": 80
          },
          "refund_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Motivo de devolución cuando status=refunded (ej.: PAYER_MISMATCH = pagó otro documento; TEST_AMOUNT = importe de prueba; PROVIDER_REJECTED)."
          },
          "refund_reason_detail": {
            "type": [
              "string",
              "null"
            ],
            "description": "Explicación legible del motivo de devolución."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "trilho": {
            "type": "string",
            "description": "Vía de esta operación: casa, corretora, saldo o liquid. No es una promesa de plazo."
          },
          "timeline": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "tempos_tipicos": {
            "type": "object",
            "description": "Mediana medida (segundos) de cada etapa, por vía, para mostrar al cliente cuánto suele tardar.",
            "additionalProperties": true
          },
          "sandbox": {
            "type": "boolean",
            "description": "True para operaciones ficticias de sandbox."
          },
          "simulation": {
            "type": "object",
            "additionalProperties": true
          },
          "delivery_mode": {
            "type": "string",
            "enum": [
              "full",
              "split"
            ],
            "description": "Solo en chain=\"liquid\": cómo se entregó el DePix. Ausente en las demás redes."
          },
          "net_cents": {
            "type": "integer",
            "description": "Solo en chain=\"liquid\" con delivery_mode=\"split\": cuánto recibe el destinatario en DePix, ya sin la tarifa. Es este importe el que Lunium envía on-chain."
          },
          "fee_total_cents": {
            "type": "integer",
            "description": "Solo en chain=\"liquid\" con delivery_mode=\"split\": todo lo descontado del bruto (tarifa fija + porcentaje). net_cents + fee_total_cents == amount_cents."
          },
          "settlement_proof": {
            "type": "string",
            "enum": [
              "none",
              "broadcast",
              "confirmed",
              "reported",
              "simulated"
            ],
            "description": "Evidencia de entrega independiente del PIX: none=sin envío completado; broadcast=tx notificada sin confirmación registrada; confirmed=recibo confirmado registrado; reported=finalización notificada sin prueba on-chain (incluye custodia/transferencia interna); simulated=prueba sin dinero real. La ausencia de confirmación no demuestra un fallo; la cobertura del verificador depende de la red y del período."
          },
          "settlement_confirmed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Cuándo se registró la confirmación on-chain. Solo se completa en settlement_proof=confirmed."
          },
          "settlement_block": {
            "type": "string",
            "nullable": true,
            "description": "Número del bloque confirmado como cadena, conservando la precisión."
          }
        }
      },
      "Payout": {
        "type": "object",
        "description": "Retiro PIX (PIX→PIX) debitado del saldo de custodia de la clave.",
        "properties": {
          "payout_id": {
            "type": "string"
          },
          "customer_ref": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 80
          },
          "status": {
            "type": "string",
            "description": "processing, sent, failed o refunded; usa los movimientos para conciliar el saldo. Deben admitirse estados nuevos."
          },
          "amount_cents": {
            "type": "integer",
            "description": "Importe que recibe el destinatario."
          },
          "fee_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tarifas totales adicionales a amount_cents: fee_service_total_cents + fee_provider_cents. Ya incluye la comisión del socio; no la sumes de nuevo."
          },
          "fee_service_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tarifa de servicio solo de Lunium en centavos registrados; componente contable. Para la interfaz del cliente y las notificaciones, usa fee_service_total_cents."
          },
          "fee_provider_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tarifa del proveedor: fee_cents menos fee_service_cents menos fee_partner_cents."
          },
          "pix_key": {
            "type": "string"
          },
          "pix_key_type": {
            "type": "string",
            "enum": [
              "cpf",
              "cnpj",
              "phone",
              "email",
              "random"
            ]
          },
          "tax_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Documento enmascarado del beneficiario, cuando se indica; opcional en la solicitud."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado.",
            "maxLength": 64
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Motivo cuando failed/refunded."
          },
          "e2e": {
            "type": [
              "string",
              "null"
            ],
            "description": "EndToEndId del PIX enviado."
          },
          "receiver_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nombre obtenido después del pago cuando está disponible. null cuando no se obtiene."
          },
          "receiver_tax_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "paid_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "verify_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Verificación pública del PIX (GET /v1/verificar/{e2e})."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "sandbox": {
            "type": "boolean",
            "description": "True para operaciones ficticias de sandbox."
          },
          "simulation": {
            "type": "object",
            "additionalProperties": true
          },
          "fee_partner_cents": {
            "type": "integer",
            "nullable": true,
            "description": "Comisión adicional del socio debitada del saldo en este retiro (centavos). Parte de fee_cents."
          },
          "fee_service_total_cents": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Tarifa de servicio combinada del cliente: tarifa Lunium registrada más comisión del socio. Conserva el redondeo original en centavos y el precio histórico; null cuando se desconoce el componente antiguo de la cuenta principal. Se incluye en las respuestas de payout y en data de los webhooks payout.*, tanto en producción como en sandbox. Suma fee_provider_cents una vez para obtener fee_cents; no vuelvas a sumar fee_partner_cents."
          }
        }
      },
      "ChaveMe": {
        "type": "object",
        "description": "Tu clave, límites vigentes y funciones habilitadas.",
        "properties": {
          "key": {
            "type": "object",
            "properties": {
              "sandbox": {
                "type": "boolean"
              },
              "key_id": {
                "type": "integer"
              },
              "prefix": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Correo electrónico indicado al crear la clave. Las claves de prueba exigen correo desde el 01/10/2026; null en claves antiguas creadas sin correo."
              },
              "cashin_enabled": {
                "type": "boolean"
              },
              "cashout_enabled": {
                "type": "boolean"
              },
              "payout_enabled": {
                "type": "boolean"
              },
              "settlement_address": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Billetera de liquidación predeterminada (Polygon); null hasta que se configure."
              },
              "chain": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "fee_bps": {
                "type": "integer"
              },
              "rate_limit_per_minute": {
                "type": "integer"
              },
              "webhook_url": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "null hasta configurarla (PATCH /keys/me): sin ella no llegan cashin.paid/settled/delayed."
              },
              "webhook_configured": {
                "type": "boolean"
              },
              "telegram_linked": {
                "type": "boolean"
              },
              "created_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "partner_fee_bps": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000,
                "description": "COMISIÓN ADICIONAL del socio, en bps, POR ENCIMA de `fee_bps` (la tarifa de Lunium). 100 = 1%. La paga el usuario final; la parte de Lunium no cambia. 0 = no se usa. Configúrala en PATCH /keys/me."
              },
              "partner_cashout_fee_bps": {
                "type": "integer",
                "description": "Comisión adicional del socio en la venta (bps). 0 = no se usa."
              },
              "partner_saque_fee_bps": {
                "type": "integer",
                "description": "Comisión adicional del socio en la salida de custodia (bps). 0 = no se usa."
              }
            }
          },
          "limits": {
            "type": "object",
            "description": "Límites y uso vigentes de la clave, por operación y pagador. null en el límite diario significa ausencia de ese límite, no de todas las restricciones. Pueden aplicarse el mandate y los límites por persona.",
            "additionalProperties": true,
            "properties": {
              "cashin_min_por_rota": {
                "type": "object",
                "description": "Mínimo en reales brasileños por moneda y red, ya con las tarifas de esta clave. min_brl_cents del cash-in en per_operation es el mínimo de la CUENTA (lo que exige la tarifa fija); el mínimo de la RED es mayor y suele ser el que provoca el rechazo. Se aplica el mayor de ambos.",
                "properties": {
                  "nota": {
                    "type": "string"
                  },
                  "rotas": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "asset": {
                          "type": "string"
                        },
                        "network": {
                          "type": "string"
                        },
                        "min_brl_cents": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "payout": {
            "type": "object",
            "description": "enabled, via, unlocks_at_settled_volume_cents, settled_volume_cents, remaining_cents.",
            "additionalProperties": true
          },
          "monitor_url": {
            "type": "string",
            "description": "Panel de seguimiento de la clave."
          },
          "telegram": {
            "type": "object",
            "additionalProperties": true
          },
          "grupos_obrigatorios": {
            "type": "object",
            "description": "Enlaces de los grupos de estado (avisos, socios, comunidad).",
            "additionalProperties": true
          },
          "comissao": {
            "type": "object",
            "description": "Comisión acumulada mediante la comisión adicional (saldo del socio). Detalles en GET /comissao.",
            "properties": {
              "partner_fee_bps": {
                "type": "integer"
              },
              "max_partner_fee_bps": {
                "type": "integer"
              },
              "disponivel_cents": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "creditado_cents": {
                "type": "integer"
              },
              "estornado_cents": {
                "type": "integer"
              },
              "sacado_cents": {
                "type": "integer"
              },
              "operacoes": {
                "type": "integer"
              },
              "ultimo_credito_em": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "moeda": {
                "type": "string"
              },
              "nota": {
                "type": "string"
              },
              "partner_cashout_fee_bps": {
                "type": "integer"
              },
              "partner_saque_fee_bps": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Catalogo": {
        "type": "object",
        "description": "Catálogo de cash-out (venta).",
        "properties": {
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "fast": {
            "type": "array",
            "description": "Pares disponibles en la vía FAST. El tiempo de depósito/PIX depende de la operación; no es un SLA fijo. Desde el 24/09/2026 incluye DEPIX/liquid, vía de la plataforma: esta fila tiene su propio min, max, tarifa y plazo.",
            "items": {
              "type": "object",
              "properties": {
                "asset": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "min": {
                  "type": "string",
                  "description": "Solo en rutas de la plataforma (DePix): mínimo por orden en reales brasileños."
                },
                "max": {
                  "type": "string",
                  "description": "Solo en rutas de la plataforma (DePix): máximo por orden en reales brasileños."
                },
                "precision": {
                  "type": "integer"
                },
                "fee_bps": {
                  "type": "integer",
                  "description": "Tarifa de Lunium en esta ruta, en bps."
                },
                "fee_fixed_cents": {
                  "type": "integer",
                  "description": "Parte fija de la tarifa de Lunium, en centavos."
                },
                "eta": {
                  "type": "string"
                },
                "nota": {
                  "type": "string"
                }
              }
            }
          },
          "dex": {
            "type": "object",
            "description": "Tokens de baja demanda mediante DEX: chains y nota.",
            "additionalProperties": true
          },
          "convert": {
            "type": "array",
            "description": "Mediante exchange: una entrada por activo con las redes aceptadas. Incluye solana y tron (06/09/2026) y las redes de dirección compartida (XRP, XLM, ATOM, HBAR, KAVA, HIVE, STEEM, IOST); en ellas, la aceptación devuelve deposit_tag.",
            "items": {
              "type": "object",
              "properties": {
                "asset": {
                  "type": "string"
                },
                "networks": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "min": {
                  "type": "string",
                  "description": "Mínimo en unidades de ESTE activo, aplicable a las redes enumeradas en el elemento. No aplicar los 6 USDT/USDC a BTC, ETH ni otros activos. También se aplica el mínimo en BRL de la operación."
                },
                "max": {
                  "type": "string",
                  "description": "Máximo en unidades de ESTE activo en la vía convert. El máximo efectivo puede ser menor por el límite en BRL, la disponibilidad diaria del destinatario y el mandate."
                },
                "precision": {
                  "type": "integer"
                },
                "deposit_eta": {
                  "type": "array",
                  "description": "Cuánto espera el cliente DESPUÉS de enviar la cripto, por red: es el plazo que debe mostrar una pantalla de VENTA. Procede de las confirmaciones que exige el exchange antes de acreditar el depósito (no confundir con el plazo de nuestro retiro, que se aplica a la compra). Ordenado de la red más rápida a la más lenta.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "network": {
                        "type": "string"
                      },
                      "confirmations": {
                        "type": "integer",
                        "description": "Confirmaciones exigidas por el exchange. Ej.: 1.000 en Base, 5.000 en Arbitrum, 61 en BSC."
                      },
                      "eta_seconds": {
                        "type": "integer",
                        "description": "Estimación en segundos = confirmaciones × tiempo de bloque de la red, redondeado hacia arriba."
                      },
                      "eta": {
                        "type": "string",
                        "description": "El mismo plazo en texto breve, ej.: \"unos 34 min\"."
                      }
                    },
                    "required": [
                      "network",
                      "confirmations",
                      "eta_seconds",
                      "eta"
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "CatalogoCompra": {
        "type": "object",
        "description": "Catálogo de cash-in (compra): lo que entregamos al recibir un PIX.",
        "properties": {
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "instant": {
            "type": "array",
            "description": "Rutas de la vía de la plataforma; puede estar vacío según la configuración. No presupongas su presencia ni un plazo fijo.",
            "items": {
              "type": "object",
              "properties": {
                "asset": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "eta": {
                  "type": "string"
                },
                "entregavel": {
                  "type": "boolean"
                },
                "min_brl_cents": {
                  "type": "integer",
                  "description": "Menor solicitud de cobro en REALES BRASILEÑOS que esta ruta entrega, ya con las tarifas de esta clave. Es la misma cifra de POST /cashin/preview (min_brl_cents) y la misma que acepta o rechaza la solicitud de cobro. Ausente cuando aún no se ha calculado para la ruta; en ese caso, lee la vista previa. Publicado desde el 24/09/2026 para USDT y USDC."
                }
              }
            }
          },
          "convert": {
            "type": "array",
            "description": "Mediante exchange: una fila por (activo, red).",
            "items": {
              "type": "object",
              "properties": {
                "asset": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "etaSeconds": {
                  "type": "integer"
                },
                "eta": {
                  "type": "string"
                },
                "fastest": {
                  "type": "boolean"
                },
                "withdrawFee": {
                  "type": "string",
                  "description": "Tarifa de retiro del exchange en esta red, en unidades del activo. Distinta de las tarifas de Lunium y del socio; ya forma parte de minBuyAmount."
                },
                "withdrawMin": {
                  "type": "string",
                  "description": "Mínimo de retiro del exchange en esta red, en unidades del activo. No es el mínimo de depósito de cripto de cash-out."
                },
                "withdrawMax": {
                  "type": "string",
                  "description": "Máximo de retiro publicado para la red, en unidades del activo. No sustituye al máximo en BRL por operación, a los límites del pagador, al saldo ni al mandate. Su ausencia no significa ilimitado."
                },
                "minBuyAmount": {
                  "type": "string",
                  "description": "Cantidad mínima QUE COMPRAR, en unidades del activo, para cubrir withdrawMin + withdrawFee en la ruta de exchange. No es necesariamente el importe neto entregado. Consulta min_brl_cents en POST /cashin/preview con la propia clave; las tarifas y el tipo de cambio modifican el mínimo en reales brasileños."
                },
                "precision": {
                  "type": "integer"
                },
                "memoRequired": {
                  "type": "boolean",
                  "description": "Red colectiva: payout_tag obligatorio."
                },
                "entregavel": {
                  "type": "boolean"
                },
                "min_brl_cents": {
                  "type": "integer",
                  "description": "Menor solicitud de cobro en REALES BRASILEÑOS que esta ruta entrega, ya con las tarifas de esta clave. Es la misma cifra de POST /cashin/preview (min_brl_cents) y la misma que acepta o rechaza la solicitud de cobro. Ausente cuando aún no se ha calculado para la ruta; en ese caso, lee la vista previa. Publicado desde el 24/09/2026 para USDT y USDC."
                }
              }
            }
          },
          "dropped": {
            "type": "array",
            "description": "Pares excluidos, con motivo (ej.: sem_par_usdt).",
            "items": {
              "type": "object",
              "properties": {
                "asset": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "motivo": {
                  "type": "string"
                }
              }
            }
          },
          "totals": {
            "type": "object",
            "additionalProperties": true
          },
          "stale": {
            "type": "boolean",
            "description": "true si el catálogo se sirvió desde la caché de contingencia."
          }
        }
      },
      "Comissao": {
        "type": "object",
        "properties": {
          "disponivel_cents": {
            "type": "integer"
          },
          "creditado_cents": {
            "type": "integer"
          },
          "estornado_cents": {
            "type": "integer"
          },
          "sacado_cents": {
            "type": "integer"
          },
          "operacoes": {
            "type": "integer"
          },
          "ultimo_credito_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "moeda": {
            "type": "string"
          },
          "sandbox": {
            "type": "boolean"
          },
          "min_saque_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "US$ 10 convertidos a la cotización ACTUAL. null = sin cotización en este momento (el retiro se rechaza)."
          },
          "pode_sacar_agora": {
            "type": "boolean"
          },
          "ultimo_saque_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "proximo_saque_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "politica": {
            "type": "object"
          }
        },
        "required": [
          "disponivel_cents",
          "creditado_cents",
          "sacado_cents",
          "operacoes",
          "moeda",
          "sandbox",
          "pode_sacar_agora",
          "politica"
        ]
      },
      "ComissaoEvento": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "credito",
              "estorno",
              "saque",
              "saque_estorno"
            ]
          },
          "valor_cents": {
            "type": "integer",
            "description": "Con signo: crédito +, reversión −, saque −, saque_estorno +."
          },
          "sentido": {
            "type": "string",
            "enum": [
              "credito",
              "debito"
            ]
          },
          "origem_id": {
            "type": "string",
            "description": "ci_... de la solicitud de cobro de compra o del retiro en cripto, po_... del retiro mediante PIX, uuid de la orden de venta, o el id del retiro de comisión (kind saque)."
          },
          "base_cents": {
            "type": "integer"
          },
          "partner_fee_bps": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "motivo": {
            "type": [
              "string",
              "null"
            ],
            "description": "Origen del asiento: vacío (compra), 'venda: cripto -> PIX', 'saida: saque por PIX', 'saida: saque em cripto', o el motivo de la reversión."
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SaqueCripto": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Cobranca"
          },
          {
            "type": "object",
            "properties": {
              "settlement_status": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Estado del crédito/entrega: sent completado; incerto requiere conciliación. PIX pagado y entrega son estados distintos.",
                "enum": [
                  "pending",
                  "sending",
                  "entregando",
                  "sent",
                  "incerto",
                  "failed",
                  null
                ]
              },
              "settlement_tx_hash": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Hash on-chain de la entrega (o id interno cuando la entrega se realiza mediante el exchange)."
              },
              "fee_cents": {
                "type": "integer",
                "description": "Tarifa de retiro de la cuenta principal debitada además de amount_cents."
              },
              "debited_cents": {
                "type": "integer",
                "description": "amount_cents más la tarifa de retiro de la cuenta principal."
              }
            }
          }
        ],
        "properties": {
          "fonte": {
            "type": "string",
            "enum": [
              "saldo"
            ]
          },
          "settlement_status": {
            "type": "string"
          },
          "fee_cents": {
            "type": "integer",
            "description": "Tarifa de Lunium debitada del saldo."
          },
          "partner_fee_cents": {
            "type": "integer",
            "description": "Comisión adicional del socio debitada del saldo por encima de la tarifa de Lunium (24/09/2026)."
          },
          "debited_cents": {
            "type": "integer",
            "description": "amount_cents + fee_cents + partner_fee_cents."
          }
        }
      },
      "CarteiraUsdt": {
        "type": "object",
        "description": "Estado y saldo de la billetera USDT del proyecto.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Billetera lista para operar ahora."
          },
          "sandbox": {
            "type": "boolean",
            "description": "Presente y true solo con una clave de prueba (simulador)."
          },
          "funding_source": {
            "type": "string",
            "enum": [
              "crypto_usdt"
            ]
          },
          "currency": {
            "type": "string",
            "enum": [
              "USDT"
            ]
          },
          "pix_rules": {
            "type": "object",
            "properties": {
              "recipient_document_required": {
                "type": "boolean"
              }
            }
          },
          "networks": {
            "type": "array",
            "description": "Redes aceptadas AHORA para depósitos, con las monedas de cada una y el plazo estimado de acreditación.",
            "items": {
              "type": "object",
              "properties": {
                "network": {
                  "type": "string",
                  "example": "polygon"
                },
                "name": {
                  "type": "string",
                  "example": "Polygon"
                },
                "assets": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "USDT",
                      "USDC"
                    ]
                  }
                },
                "eta_minutes": {
                  "type": [
                    "integer",
                    "null"
                  ]
                }
              }
            }
          },
          "balance": {
            "type": "object",
            "properties": {
              "available": {
                "type": "string",
                "pattern": "^-?\\d+\\.\\d{6}$",
                "description": "Disponible para Pix o retiro en cripto, en USDT (6 decimales)."
              },
              "reserved": {
                "type": "string",
                "pattern": "^-?\\d+\\.\\d{6}$",
                "description": "Reservado por Pix y retiros en cripto en curso."
              },
              "confirming": {
                "type": "string",
                "pattern": "^-?\\d+\\.\\d{6}$",
                "description": "Depósitos detectados, pendientes de confirmación de la custodia."
              }
            }
          },
          "min_deposit": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": "Depósito mínimo en USDT."
          },
          "min_payment_brl": {
            "type": "string",
            "example": "25.00",
            "description": "Menor Pix pagado con USDT, en reales brasileños."
          },
          "deposit_validity_hours": {
            "type": "number",
            "description": "Validez de una solicitud de depósito, en horas (actualmente 1)."
          },
          "payments_enabled": {
            "type": "boolean"
          },
          "withdrawals_enabled": {
            "type": "boolean",
            "description": "Retiros nuevos habilitados; las consultas y el seguimiento continúan después de bloquear operaciones nuevas."
          },
          "payment_methods": {
            "type": "object",
            "properties": {
              "pix_key": {
                "type": "boolean"
              },
              "br_code": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "DepositoCarteira": {
        "type": "object",
        "description": "Solicitud de depósito. El IMPORTE EXACTO que llega identifica el depósito: envía `amount_to_send` en la red indicada antes de `expires_at`.",
        "properties": {
          "deposit_id": {
            "type": "string",
            "example": "ud_3f9c0a1b2c3d4e5f6a7b"
          },
          "status": {
            "type": "string",
            "enum": [
              "waiting",
              "confirming",
              "available",
              "expired",
              "under_review",
              "reversed"
            ],
            "description": "`waiting` esperando el envío · `confirming` detectado, confirmando · `available` acreditado en el saldo · `expired` el plazo venció sin depósito · `under_review` en revisión · `reversed` revertido."
          },
          "amount_to_send": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": "Importe exacto que enviar (los últimos decimales identifican tu depósito)."
          },
          "amount_received": {
            "type": [
              "string",
              "null"
            ],
            "description": "Lo que llegó (crédito)."
          },
          "address": {
            "type": "string",
            "description": "Dirección de destino en la red elegida. En pruebas es ficticia (`SANDBOX-NAO-ENVIE-FUNDOS`)."
          },
          "network": {
            "type": "string"
          },
          "network_name": {
            "type": "string"
          },
          "asset": {
            "type": "string"
          },
          "accepted_assets": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Plazo de la solicitud: 1 hora desde la creación (`created_at` + `deposit_validity_hours`). Envía dentro del plazo."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "credited_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "origin": {
            "type": "string",
            "enum": [
              "request",
              "assigned_by_support"
            ]
          },
          "instructions": {
            "type": "string",
            "description": "Solo al crear: el texto que se mostrará al usuario."
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "LancamentoCarteira": {
        "type": "object",
        "description": "Fila de movimientos. `amount` siempre es positivo; `type` indica la dirección.",
        "properties": {
          "entry_id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "deposit",
              "reserve",
              "release",
              "debit",
              "reversal"
            ],
            "description": "`deposit` crédito de depósito · `reserve` reserva para Pix o retiro en cripto · `debit` operación completada · `release` reserva devuelta al disponible · `reversal` depósito revertido."
          },
          "amount": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": ""
          },
          "available_after": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": ""
          },
          "reserved_after": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": ""
          },
          "reference": {
            "type": "string",
            "description": "`payment_id` del Pix, `withdrawal_id` del retiro en cripto, `deposit` o `adjustment`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "operation_type": {
            "type": "string",
            "enum": [
              "deposit",
              "pix_payment",
              "crypto_withdrawal"
            ]
          }
        }
      },
      "CotacaoPixCarteira": {
        "type": "object",
        "description": "Vista previa de un Pix pagado con USDT. Estimación: al confirmar, se vuelve a cotizar y reservamos hasta un 1% más (el sobrante vuelve).",
        "properties": {
          "payment_method": {
            "type": "string",
            "enum": [
              "pix_key",
              "br_code"
            ]
          },
          "brl_amount": {
            "type": "string",
            "example": "50.00"
          },
          "usdt_order": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": "USDT convertidos para pagar el Pix."
          },
          "withdrawal_fee": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": "Coste de envío."
          },
          "usdt_total": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": "Total estimado debitado."
          },
          "usdt_reserved": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": "Cuánto queda reservado hasta que se complete el Pix."
          },
          "quote_id": {
            "type": "string",
            "description": "Solo con br_code: envíalo en POST /carteira-usdt/payments para garantizar que sea el mismo código."
          },
          "merchant_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "pix_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "pix_key_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "note": {
            "type": "string"
          },
          "sandbox": {
            "type": "boolean"
          },
          "reserve_usd": {
            "type": [
              "string",
              "null"
            ],
            "description": "Equivalente en USDT de la reserva operativa de R$1, convertido al cotizar y ya incluido en el total; no lo sumes de nuevo. Las órdenes antiguas conservan su valor original. / Equivalente en USDT de la reserva operativa de BRL 1, convertido al cotizar y ya incluido en el total; no lo añadas de nuevo. Las órdenes existentes conservan su valor original.",
            "example": "0.200000"
          },
          "reserve_brl": {
            "type": [
              "string",
              "null"
            ],
            "example": "1.00",
            "description": "Reserva operativa fija de R$1 en las órdenes nuevas, ya incluida en el total. Las antiguas conservan la reserva original. / Reserva operativa fija de BRL 1 en las órdenes nuevas, ya incluida en el total; las órdenes existentes conservan su reserva original."
          }
        }
      },
      "PagamentoCarteira": {
        "type": "object",
        "description": "Pix pagado con el saldo USDT.",
        "properties": {
          "payment_id": {
            "type": "string",
            "example": "cu_8a7b6c5d4e3f2a1b0c9d"
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "reservado",
              "ordem_criada",
              "aceita",
              "sacando",
              "enviado",
              "revisao",
              "concluido",
              "falhou",
              "falhou_apos_envio"
            ],
            "description": "Finales: `concluido` (Pix pagado), `falhou` (no ejecutado; la reserva volvió al saldo), `falhou_apos_envio` (en investigación; la reserva NO vuelve automáticamente). `revisao`: en revisión, no es un fallo; haz el seguimiento. Los demás son etapas en curso."
          },
          "final": {
            "type": "boolean",
            "description": "true cuando el estado ya no cambia."
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "pix_key",
              "br_code"
            ]
          },
          "brl_amount": {
            "type": "string"
          },
          "pix_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Enmascarada."
          },
          "usdt_reserved": {
            "type": "string",
            "pattern": "^-?\\d+\\.\\d{6}$",
            "description": ""
          },
          "usdt_debited": {
            "type": [
              "string",
              "null"
            ]
          },
          "usdt_order": {
            "type": [
              "string",
              "null"
            ]
          },
          "withdrawal_fee": {
            "type": [
              "string",
              "null"
            ]
          },
          "cashout_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "La orden que pagó el Pix (GET /cash-outs/{cashout_id} tiene los detalles)."
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "pix_e2e": {
            "type": "string",
            "description": "Solo en `concluido`: el identificador E2E del Pix."
          },
          "recipient_name": {
            "type": "string",
            "description": "Solo en `concluido`: nombre de quien recibió."
          },
          "recipient_document": {
            "type": [
              "string",
              "null"
            ],
            "description": "Solo en `concluido`: CPF parcial (formato del Banco Central) o CNPJ."
          },
          "receipt_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Solo en `concluido`: enlace público del comprobante oficial (null en pruebas)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "schema": {
          "type": "integer"
        },
        "description": "Máximo de solicitudes por minuto de esta clave (= rate_limit_per_minute)."
      },
      "X-RateLimit-Remaining": {
        "schema": {
          "type": "integer"
        },
        "description": "Cuántas solicitudes caben aún en la ventana actual."
      },
      "X-RateLimit-Reset": {
        "schema": {
          "type": "integer"
        },
        "description": "Segundos hasta que el depósito de cuota se recargue por completo."
      },
      "Retry-After": {
        "schema": {
          "type": "integer"
        },
        "description": "Solo en 429: segundos que esperar antes de repetir."
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/carteira-usdt/withdrawals/networks": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Rutas para retirar el saldo en cripto",
        "description": "Usa solo los pares devueltos actualmente; que el depósito esté habilitado no garantiza que lo esté el retiro. Polygon, BSC, Tron, Ethereum, Arbitrum, Optimism, Base, Avalanche y Solana usan los mismos identificadores de entrada. Tron: USDT; Base: USDC.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "asset": {
                            "type": "string",
                            "enum": [
                              "USDT",
                              "USDC"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "polygon",
                              "bsc",
                              "tron",
                              "eth",
                              "arbitrum",
                              "optimism",
                              "base",
                              "avalanche",
                              "solana"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "min_received": {
                            "type": "string",
                            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
                          },
                          "network_fee": {
                            "type": "string",
                            "pattern": "^\\d+(?:\\.\\d{1,6})?$"
                          },
                          "precision": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "funding_source": {
                      "type": "string",
                      "enum": [
                        "crypto_usdt"
                      ]
                    },
                    "fee_mode": {
                      "type": "string",
                      "enum": [
                        "deducted"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Cuerpo no válido, red no disponible o importe inferior al mínimo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "carteira_nao_liberada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Cotización caducada, saldo insuficiente o external_id divergente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "La operación existente sigue en seguimiento; recupera la misma solicitud.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/withdrawals/quote": {
      "post": {
        "tags": [
          "Billetera USDT"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Vista previa de retiro en cripto sin reserva",
        "description": "Indica el total en USDT (5 a 100000, hasta dos decimales), la moneda, la red y la dirección externa. La vista previa dura 120 segundos y no reserva saldo. Los costes se descuentan del total; Lunium paga el gas de Polygon. USDC tiene en cuenta la conversión y el mínimo neto autorizado con hasta un 0,5% de variación respecto a la estimación. No hay una tarifa de servicio adicional en este flujo de saldo USDT. Esto no modifica las tarifas de retiro del saldo BRL. Las claves de prueba usan las mismas rutas, sin dinero real: tarifa simulada 0.01; terminaciones .01 revisión, .02 fallo antes del envío y .05 lento. El hash de prueba comienza por SANDBOX-. Lista limitada a los 100 más recientes; el ID y external_id siguen siendo consultables.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CotacaoSaqueCriptoCarteira"
                }
              }
            }
          },
          "400": {
            "description": "Cuerpo no válido, red no disponible o importe inferior al mínimo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "carteira_nao_liberada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Cotización caducada, saldo insuficiente o external_id divergente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "La operación existente sigue en seguimiento; recupera la misma solicitud.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "funding_source",
                  "amount",
                  "asset",
                  "network",
                  "address"
                ],
                "properties": {
                  "funding_source": {
                    "type": "string",
                    "enum": [
                      "crypto_usdt"
                    ]
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^\\d{1,9}(?:\\.\\d{1,2})?$"
                  },
                  "asset": {
                    "type": "string",
                    "enum": [
                      "USDT",
                      "USDC"
                    ]
                  },
                  "network": {
                    "type": "string",
                    "enum": [
                      "polygon",
                      "bsc",
                      "tron",
                      "eth",
                      "arbitrum",
                      "optimism",
                      "base",
                      "avalanche",
                      "solana"
                    ]
                  },
                  "address": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/withdrawals": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Listar los retiros en cripto",
        "description": "Estados: reserved, funding, converting, processing, under_review, completed, failed. Solo completed/failed son finales. La incertidumbre conserva la reserva. completed exige confirmación del envío y tx_hash; failed libera la reserva solo con prueba de no envío/reversión. No hay cancelación pública después de confirmar. Webhooks firmados: wallet.withdrawal.completed / wallet.withdrawal.failed, data igual al recurso. Consulta el GET aunque se retrase el webhook. Las claves de prueba usan las mismas rutas, sin dinero real: tarifa simulada 0.01; terminaciones .01 revisión, .02 fallo antes del envío y .05 lento. El hash de prueba comienza por SANDBOX-. Lista limitada a los 100 más recientes; el ID y external_id siguen siendo consultables.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SaqueCriptoCarteira"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Cuerpo no válido, red no disponible o importe inferior al mínimo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "carteira_nao_liberada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Cotización caducada, saldo insuficiente o external_id divergente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "La operación existente sigue en seguimiento; recupera la misma solicitud.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Billetera USDT"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Confirmar el retiro del saldo USDT",
        "description": "Envía solo funding_source, quote_id y external_id (8–64 caracteres). La reserva es atómica y compartida con Pix. La respuesta 201 crea; 200 recupera. La misma cotización o intención activa no genera otro retiro, incluso con otra referencia. Conserva el cuerpo y external_id después de un timeout/5xx; consulta external/{external_id}. Un 404 en la consulta no demuestra un rechazo: solo repite el mismo cuerpo, nunca crees una referencia nueva. La red/dirección no cambian tras confirmar. Estados: reserved, funding, converting, processing, under_review, completed, failed. Solo completed/failed son finales. La incertidumbre conserva la reserva. completed exige confirmación del envío y tx_hash; failed libera la reserva solo con prueba de no envío/reversión. No hay cancelación pública tras confirmar. Webhooks firmados: wallet.withdrawal.completed / wallet.withdrawal.failed, data igual al recurso. Consulta el GET aunque se retrase el webhook.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaqueCriptoCarteira"
                }
              }
            }
          },
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaqueCriptoCarteira"
                }
              }
            }
          },
          "400": {
            "description": "Cuerpo no válido, red no disponible o importe inferior al mínimo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "carteira_nao_liberada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Cotización caducada, saldo insuficiente o external_id divergente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "La operación existente sigue en seguimiento; recupera la misma solicitud.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "funding_source",
                  "quote_id",
                  "external_id"
                ],
                "properties": {
                  "funding_source": {
                    "type": "string",
                    "enum": [
                      "crypto_usdt"
                    ]
                  },
                  "quote_id": {
                    "type": "string",
                    "pattern": "^uq_[a-f0-9]{24}$"
                  },
                  "external_id": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_.:-]{7,63}$"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/withdrawals/{withdrawal_id}": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Consultar un retiro en cripto",
        "description": "Envía solo funding_source, quote_id y external_id (8–64 caracteres). La reserva es atómica y compartida con Pix. La respuesta 201 crea; 200 recupera. La misma cotización o intención activa no genera otro retiro, incluso con otra referencia. Conserva el cuerpo y external_id después de un timeout/5xx; consulta external/{external_id}. Un 404 en la consulta no demuestra un rechazo: solo repite el mismo cuerpo, nunca crees una referencia nueva. La red/dirección no cambian tras confirmar. Estados: reserved, funding, converting, processing, under_review, completed, failed. Solo completed/failed son finales. La incertidumbre conserva la reserva. completed exige confirmación del envío y tx_hash; failed libera la reserva solo con prueba de no envío/reversión. No hay cancelación pública tras confirmar. Webhooks firmados: wallet.withdrawal.completed / wallet.withdrawal.failed, data igual al recurso. Consulta el GET aunque se retrase el webhook.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaqueCriptoCarteira"
                }
              }
            }
          },
          "400": {
            "description": "Cuerpo no válido, red no disponible o importe inferior al mínimo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "carteira_nao_liberada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "nao_encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Cotización caducada, saldo insuficiente o external_id divergente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "La operación existente sigue en seguimiento; recupera la misma solicitud.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "withdrawal_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/carteira-usdt/withdrawals/external/{external_id}": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Recuperar mediante la referencia original",
        "description": "Envía solo funding_source, quote_id y external_id (8–64 caracteres). La reserva es atómica y compartida con Pix. La respuesta 201 crea; 200 recupera. La misma cotización o intención activa no genera otro retiro, incluso con otra referencia. Conserva el cuerpo y external_id después de un timeout/5xx; consulta external/{external_id}. Un 404 en la consulta no demuestra un rechazo: solo repite el mismo cuerpo, nunca crees una referencia nueva. La red/dirección no cambian tras confirmar. Estados: reserved, funding, converting, processing, under_review, completed, failed. Solo completed/failed son finales. La incertidumbre conserva la reserva. completed exige confirmación del envío y tx_hash; failed libera la reserva solo con prueba de no envío/reversión. No hay cancelación pública tras confirmar. Webhooks firmados: wallet.withdrawal.completed / wallet.withdrawal.failed, data igual al recurso. Consulta el GET aunque se retrase el webhook.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaqueCriptoCarteira"
                }
              }
            }
          },
          "400": {
            "description": "Cuerpo no válido, red no disponible o importe inferior al mínimo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "carteira_nao_liberada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "nao_encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Cotización caducada, saldo insuficiente o external_id divergente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "La operación existente sigue en seguimiento; recupera la misma solicitud.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/leads": {
      "post": {
        "tags": [
          "Contacto"
        ],
        "operationId": "contactIntegrationTeam",
        "summary": "Derivar un caso comercial o técnico a una persona",
        "description": "Ruta pública, sin clave. Úsala solo para precios por volumen, contratos, colaboraciones o casos que la documentación no resuelva. La dirección debe haber sido facilitada por la propia persona para este contacto; no busques, extraigas ni reutilices correos obtenidos para otro fin. Para empezar sin hablar con nadie, usa `POST /keys/sandbox`.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "consentimento"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 200
                  },
                  "nome": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "empresa": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "whatsapp": {
                    "type": "string",
                    "maxLength": 40
                  },
                  "mensagem": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "fluxo": {
                    "type": "string",
                    "enum": [
                      "cashin",
                      "cashout",
                      "cashin_cashout",
                      "payout",
                      "outro",
                      "custody"
                    ]
                  },
                  "volume_mensal": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "prazo": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "estagio_produto": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "como_encontrou": {
                    "type": "string",
                    "description": "Fuente declarada por la persona, separada del UTM. Ej.: chatgpt, google, indicacao."
                  },
                  "consentimento": {
                    "type": "boolean",
                    "const": true,
                    "description": "Confirma que la persona facilitó sus datos de contacto para recibir una respuesta a esta solicitud."
                  },
                  "origem": {
                    "type": "string",
                    "description": "Página o contexto donde se inició la solicitud."
                  },
                  "utm_source": {
                    "type": "string"
                  },
                  "utm_medium": {
                    "type": "string"
                  },
                  "utm_campaign": {
                    "type": "string"
                  },
                  "utm_content": {
                    "type": "string"
                  },
                  "utm_term": {
                    "type": "string"
                  },
                  "ref_agent": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string",
                    "description": "Honeypot: los clientes legítimos deben omitirlo o enviarlo vacío."
                  }
                }
              },
              "examples": {
                "empresa_vinda_do_chatgpt": {
                  "value": {
                    "email": "integracao@empresa.com.br",
                    "empresa": "Empresa Exemplo",
                    "fluxo": "cashin_cashout",
                    "volume_mensal": "R$ 250 mil a R$ 1 milhão",
                    "prazo": "Neste mês",
                    "como_encontrou": "chatgpt",
                    "consentimento": true,
                    "utm_source": "chatgpt",
                    "utm_medium": "answer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contacto existente actualizado dentro de la ventana de deduplicación. Con consentimiento explícito, devuelve un nuevo lead_token e invalida el anterior.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "lead_id": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "lead_token": {
                      "type": "string",
                      "pattern": "^ldt_[A-Za-z0-9_-]{43}$",
                      "minLength": 47,
                      "maxLength": 47,
                      "description": "Token opaco de atribución devuelto con consentimiento explícito. Envíalo solo en POST /keys, POST /keys/sandbox o lunium_start_sandbox_demo. Nunca lo incluyas en URLs ni registros."
                    },
                    "detail": {
                      "type": "string"
                    },
                    "integration_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Inicia inmediatamente la integración de autoservicio; el contacto humano es opcional."
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Contacto recibido. Con consentimiento explícito, lead_token vincula este contacto con la clave que se cree a continuación.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "lead_id"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "lead_id": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "lead_token": {
                      "type": "string",
                      "pattern": "^ldt_[A-Za-z0-9_-]{43}$",
                      "minLength": 47,
                      "maxLength": 47,
                      "description": "Token opaco de atribución devuelto con consentimiento explícito. Envíalo solo en POST /keys, POST /keys/sandbox o lunium_start_sandbox_demo. Nunca lo incluyas en URLs ni registros."
                    },
                    "detail": {
                      "type": "string"
                    },
                    "integration_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Inicia inmediatamente la integración de autoservicio; el contacto humano es opcional."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Correo electrónico o cuerpo no válido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "Demasiados intentos desde la misma dirección.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "No se pudo guardar el contacto; inténtalo de nuevo o usa el correo electrónico publicado."
          }
        },
        "externalDocs": {
          "description": "Página para obtener acceso al sandbox y hablar con el equipo de integración",
          "url": "https://luniumpay.com/integrar?utm_source=openapi&utm_medium=spec"
        }
      }
    },
    "/v1/verificar/{e2e}": {
      "get": {
        "tags": [
          "Verificación"
        ],
        "operationId": "verificarPagamento",
        "security": [],
        "summary": "Confirmar que se realizó un PIX (abierto, sin clave)",
        "description": "Permite comprobar un pago sin depender de la palabra de quien afirma haber pagado. No requiere cuenta ni clave. No devuelve la clave PIX, el nombre completo ni el documento: acredita el pago sin exponer a las partes. Cuando no lo encuentra, la respuesta indica explícitamente que el PIX puede haberse realizado mediante otra institución: su ausencia aquí no demuestra que no existiera.",
        "parameters": [
          {
            "name": "e2e",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del Banco Central: E + 32 caracteres.",
            "example": "E37293930202607312006361894c4a82"
          }
        ],
        "responses": {
          "200": {
            "description": "Pago liquidado por Lunium.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verificado": {
                      "type": "boolean"
                    },
                    "pago": {
                      "type": "boolean"
                    },
                    "e2e": {
                      "type": "string",
                      "description": "Identificador de extremo a extremo del Banco Central, repetido en la respuesta (letra E + código del comprobante). Cualquier tercero puede volver a validarlo en este mismo endpoint."
                    },
                    "valor_brl": {
                      "type": "string"
                    },
                    "pago_em": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-08-01T22:35:49-03:00",
                      "description": "ISO 8601 CON offset (hora de Brasilia). Nunca presupongas UTC ni la hora local: el offset es explícito. / (es) ISO 8601 con offset explícito (hora de Brasilia)."
                    },
                    "recebedor_iniciais": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "instituicao": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "liquidado_por": {
                      "type": "string"
                    },
                    "comprovante_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No liquidado por Lunium (puede haberlo sido por otra institución)."
          },
          "400": {
            "description": "Formato no válido."
          }
        },
        "x-lunium-capability": [
          "payment_verification"
        ],
        "x-lunium-intents": [
          "verify_payment",
          "prove_settlement"
        ],
        "x-lunium-agent-safe": true
      }
    },
    "/catalog": {
      "get": {
        "tags": [
          "Catálogo"
        ],
        "operationId": "obterCatalogo",
        "summary": "Activos, redes y límites que permiten liquidar ahora",
        "description": "Catálogo de entrada de cripto para cash-out. Usa los pares devueltos actualmente y sus mínimos, máximos y estimaciones; no mantengas una lista fija de redes. fast, convert y dex describen vías distintas. La disponibilidad difiere del catálogo de entrega /cashin/catalog. Si la aceptación devuelve deposit_tag, debe acompañar al depósito. stale=true indica contingencia. Con una clave lun_test_, DEPIX/liquid aparece en fast como simulación; usa asset=DEPIX&network=liquid para filtrar.",
        "responses": {
          "200": {
            "description": "Catálogo en directo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalogo"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/cash-outs": {
      "post": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "criarCotacao",
        "summary": "Cotizar (paso 1 de 3)",
        "description": "Crea una cotización de cripto externa a PIX; la dirección de depósito solo se obtiene en accept. Elige un par de GET /catalog y uno de los tres modos: amount + pix_key, brl_amount + pix_key, o br_code completo sin los demás campos de importe/destinatario. Los importes son cadenas decimales. Lee los límites por operación/clave en GET /keys/me y los límites efectivos/del destinatario en la respuesta. El mandate puede restringir la operación. La ruta de br_code exige USDT/USDC compatible y puede devolver 503 br_code_indisponivel tanto en la vista previa como en la creación. El sandbox es simulado y no demuestra la disponibilidad en producción. Producción responde 200 al crear; sandbox puede responder 201. Repite external_id solo con la misma solicitud original; ante un conflicto, consulta la orden indicada en recovery_endpoint. DePix/Liquid también acepta amount o brl_amount y exige el CPF/CNPJ del beneficiario (payee_tax_number para claves Pix de correo electrónico, teléfono o aleatorias); refund_address es opcional desde la 1.44.0: si la venta requiere una devolución y la orden no tiene billetera, se detiene en AWAITING_REFUND_ADDRESS (webhook cashout.awaiting_refund_address) hasta que indiques la billetera Liquid del cliente en POST /cash-outs/{cashout_id}/refund-address. En sandbox, DePix usa la paridad BRL y la tarifa de venta de la clave; accept inicia un depósito ficticio automático y se completa en unos 14 segundos. Nunca envíes monedas a la dirección SANDBOX:LIQUID:NAO_ENVIAR:. Guía: https://docs.luniumpay.com/sandbox#depix-pix.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "asset",
                  "network"
                ],
                "properties": {
                  "asset": {
                    "type": "string",
                    "examples": [
                      "USDT",
                      "DEPIX"
                    ],
                    "description": "Activo vendido. Usa el id EXACTO de GET /catalog (ej.: \"usdt\"). Combínalo con network: el par (asset, network) debe existir en el catálogo."
                  },
                  "network": {
                    "type": "string",
                    "description": "Red de entrada de criptomonedas publicada en GET /catalog. No la confundas con las redes de entrega de /cashin/catalog.",
                    "examples": [
                      "polygon",
                      "liquid"
                    ]
                  },
                  "amount": {
                    "type": "string",
                    "description": "Cantidad de cripto en cadena decimal (\"50\"), nunca float. No la combines con brl_amount ni br_code. Al crear la orden, este modo exige pix_key.",
                    "examples": [
                      "50"
                    ]
                  },
                  "brl_amount": {
                    "type": "string",
                    "description": "Objetivo en reales brasileños para la cotización inversa, en cadena decimal con hasta 2 decimales (\"250.00\"). No lo combines con amount ni br_code. Al crear la orden, este modo exige pix_key. La respuesta indica la cantidad exacta de cripto que depositar y el importe efectivo en reales brasileños, que puede diferir del objetivo por redondeo. Muestra los valores devueltos antes de aceptar. Los mínimos y límites dependen de la ruta, la clave y el destinatario; consulta los valores vigentes. (es) Importe BRL objetivo; revisa el BRL efectivo cotizado y la cantidad exacta de depósito de cripto antes de aceptar.",
                    "examples": [
                      "250.00"
                    ]
                  },
                  "pix_key": {
                    "type": "string",
                    "description": "Clave que recibirá los reales brasileños. Formatos aceptados (normalizados por la API al formato exacto del liquidador; fuera de ellos → 400 pix_key_invalida antes de que exista un depósito): CPF 11 dígitos · CNPJ 14 dígitos · teléfono internacional +55DDDNÚMERO (+5548996005588) · correo electrónico · clave aleatoria en UUID (6602ede6-b1a9-4e63-9178-c6883fd0095e). (es) Clave que recibe los reales brasileños. Formatos aceptados: CPF 11 dígitos · CNPJ 14 dígitos · teléfono +55 + prefijo de zona + número · correo electrónico · clave aleatoria como UUID."
                  },
                  "pix_key_type": {
                    "type": "string",
                    "enum": [
                      "cpf",
                      "cnpj",
                      "phone",
                      "email",
                      "random"
                    ],
                    "description": "Opcional: se deduce del formato de la clave (correo, CNPJ, UUID o teléfono con +55). Solo es obligatorio cuando la clave tiene 11 dígitos puros, donde CPF y teléfono son indistinguibles; en ese caso, la API rechaza con el error tipo_ambiguo en lugar de adivinar."
                  },
                  "token_address": {
                    "type": "string",
                    "description": "Dirección/mint exacto. Necesario para los tokens de `/catalog/dex`, donde los símbolos se repiten."
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Identificador persistente por intención, de hasta 64 caracteres. Repetir el mismo cuerpo reutiliza la orden. Cambiar la red, activo, token, destino, tipo PIX, importe o billetera de retorno genera un conflicto 409; recupera la original antes de decidir una operación nueva. Las órdenes antiguas sin identidad verificable pueden exigir recuperación por cashout_id/external_id.",
                    "maxLength": 64
                  },
                  "refund_address": {
                    "type": "string",
                    "description": "Billetera de devolución del cliente, compatible con la red y confirmada por él. No la deduzcas del origen on-chain. Sin billetera, el flujo puede detenerse en AWAITING_REFUND_ADDRESS; consulta refund_asset, refund_network y refund_amount cuando se devuelvan. En la venta de DePix, es opcional desde la 1.44.0 (antes era obligatoria); si se indica, debe ser una dirección Liquid válida (lq1…) del cliente, también en el sandbox.",
                    "examples": [
                      "0x51e3d44172868acc60d68ca99591ce4230bc75e0"
                    ]
                  },
                  "br_code": {
                    "type": "string",
                    "description": "Copia y Pega de una solicitud de cobro PIX con importe definido, cuando la función esté disponible. USDT/USDC; sustituye a pix_key, amount y brl_amount. Puede devolver 503 br_code_indisponivel en producción. El amount cotizado incluye una reserva fija de R$ 1,00 (reserve_brl; equivalente en USDT en el campo copia_e_cola_buffer_usd) que garantiza el PIX por el importe exacto del QR; el sobrante queda en Lunium como reserva de corrección y no se devuelve. Si el cliente pegó o escaneó un QR con importe —estático o dinámico—, envía br_code completo, nunca pix_key + brl_amount extraídos de él: solo así se envía el PIX por el importe exacto y como pago de esa solicitud de cobro (con el txid). Al pagar por clave, el importe puede variar en centavos y el destinatario no lo reconoce.",
                    "examples": [
                      "00020126330014br.gov.bcb.pix0111498113948905204000053039865406…6304ABCD"
                    ],
                    "minLength": 40,
                    "maxLength": 512
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "enum": [
                      "success",
                      "delayed",
                      "failed",
                      "expired",
                      "refunded",
                      "settlement_uncertain",
                      "provider_unavailable",
                      "route_unavailable",
                      "no_deposit"
                    ],
                    "description": "Solo DePix/Liquid en sandbox. Prevalece sobre los activadores por centavos. Sin escenario explícito, los activadores .01 a .08 siguen activos. Una clave de producción devuelve 403 sandbox_only. Consulta GET /sandbox para ver los escenarios por flujo."
                  },
                  "payee_tax_number": {
                    "type": "string",
                    "description": "DePix/Liquid: CPF (11 dígitos) o CNPJ (14 dígitos) del destinatario. Obligatorio para claves PIX email, phone o random. Para claves cpf/cnpj, se usa el documento de la propia clave. Nunca uses documentos sintéticos en producción."
                  }
                },
                "oneOf": [
                  {
                    "required": [
                      "pix_key",
                      "amount"
                    ],
                    "not": {
                      "anyOf": [
                        {
                          "required": [
                            "brl_amount"
                          ]
                        },
                        {
                          "required": [
                            "br_code"
                          ]
                        }
                      ]
                    }
                  },
                  {
                    "required": [
                      "pix_key",
                      "brl_amount"
                    ],
                    "not": {
                      "anyOf": [
                        {
                          "required": [
                            "amount"
                          ]
                        },
                        {
                          "required": [
                            "br_code"
                          ]
                        }
                      ]
                    }
                  },
                  {
                    "required": [
                      "br_code"
                    ],
                    "not": {
                      "anyOf": [
                        {
                          "required": [
                            "amount"
                          ]
                        },
                        {
                          "required": [
                            "brl_amount"
                          ]
                        },
                        {
                          "required": [
                            "pix_key"
                          ]
                        },
                        {
                          "required": [
                            "pix_key_type"
                          ]
                        }
                      ]
                    }
                  }
                ]
              },
              "examples": {
                "usdt": {
                  "summary": "USDT en Polygon",
                  "value": {
                    "asset": "USDT",
                    "network": "polygon",
                    "amount": "50",
                    "pix_key": "12345678901",
                    "pix_key_type": "cpf",
                    "refund_address": "0x51e3d44172868acc60d68ca99591ce4230bc75e0",
                    "external_id": "saque-4471"
                  }
                },
                "reverso": {
                  "summary": "A partir del importe en reales brasileños (cotización inversa)",
                  "value": {
                    "asset": "USDT",
                    "network": "polygon",
                    "brl_amount": "250.00",
                    "pix_key": "vendas@loja.com.br",
                    "external_id": "pedido-9921"
                  }
                },
                "cobranca": {
                  "summary": "Pagar un código QR / Copia y Pega (USDT/USDC en cualquier red del catálogo)",
                  "value": {
                    "asset": "USDC",
                    "network": "polygon",
                    "br_code": "00020126330014br.gov.bcb.pix0111498113948905204000053039865406…6304ABCD",
                    "refund_address": "0x51e3d44172868acc60d68ca99591ce4230bc75e0",
                    "external_id": "pedido-9922"
                  }
                },
                "depix_sandbox": {
                  "summary": "DePix → PIX ficticio (solo clave lun_test_; sustituye la billetera de devolución)",
                  "value": {
                    "asset": "DEPIX",
                    "network": "liquid",
                    "amount": "100.00",
                    "pix_key": "depix@example.invalid",
                    "pix_key_type": "email",
                    "payee_tax_number": "12345678901",
                    "refund_address": "SUA_CARTEIRA_LIQUID_DE_DEVOLUCAO",
                    "external_id": "sandbox-depix-pix-001",
                    "sandbox_scenario": "success"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cotización creada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashOut"
                }
              }
            }
          },
          "200": {
            "description": "Cotización creada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashOut"
                }
              }
            }
          },
          "400": {
            "description": "Solicitud no válida o red no disponible.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "`external_id` ya utilizado con otros parámetros."
          },
          "422": {
            "description": "Parámetros semánticamente no válidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "sandbox_scenario exige una clave de prueba; no se creó ninguna orden."
          },
          "503": {
            "description": "Servicio no disponible; en el escenario de prueba provider_unavailable no se crea ninguna orden."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-lunium-capability": [
          "usdt_to_pix",
          "usdc_to_pix",
          "crypto_to_pix"
        ],
        "x-lunium-intents": [
          "sell_crypto",
          "receive_fiat",
          "offramp",
          "cash_out"
        ],
        "x-lunium-reward-eligible": true
      },
      "get": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "listarCashOuts",
        "summary": "Listar órdenes",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "description": "Recuperación idempotente: devuelve la operación con este external_id (0 o 1). Único por clave y producto, distingue mayúsculas y minúsculas y se conserva de forma permanente."
          }
        ],
        "responses": {
          "200": {
            "description": "Órdenes de tu clave, de más recientes a más antiguas."
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/cash-outs/{cashout_id}/accept": {
      "post": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "aceitarCotacao",
        "summary": "Aceptar y obtener la dirección (paso 2 de 3)",
        "description": "Fija la cotización y devuelve `deposit_address`. Envía **exactamente** la cantidad cotizada. Si la red exige memo/tag, se devuelve en `deposit_tag`: un depósito sin el memo se pierde.",
        "parameters": [
          {
            "name": "cashout_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dirección de depósito.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashOut"
                }
              }
            }
          },
          "404": {
            "description": "Orden no encontrada."
          },
          "422": {
            "description": "Cotización caducada o ya aceptada."
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/cash-outs/{cashout_id}": {
      "get": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "consultarCashOut",
        "summary": "Hacer seguimiento (paso 3 de 3)",
        "description": "Prefiere el webhook. Si consultas, hazlo una vez cada 10–15 s: una vez por segundo consume por sí sola el límite de 60 solicitudes por minuto de la clave. COMPLETED indica un pago completado; pix_e2e, pix_paid_at y los enlaces del comprobante pueden llegar después. Presenta los campos disponibles y sigue la misma orden o el evento cashout.receipt_ready. La ausencia momentánea del comprobante no es motivo para crear otro pago.",
        "parameters": [
          {
            "name": "cashout_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estado actual.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashOut"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/cashin/charge": {
      "post": {
        "tags": [
          "Cash-in"
        ],
        "operationId": "criarCobranca",
        "summary": "Generar una solicitud de cobro PIX para custodia BRL o entrega de criptomonedas",
        "description": "Genera PIX para custodia BRL (destino=saldo, sin billetera) o entrega directa de criptomonedas (destino=cripto, predeterminado). Indica el documento de quien pagará. Consulta GET /cashin/limits y las condiciones de la clave. Los límites, las tarifas y el proveedor determinan el mínimo efectivo; la creación vuelve a validar. La retención puede producirse en el proveedor (held_hours/delay_until) o localmente (hold_hours/liberar_em). PIX paid no significa entrega/abono completado: sigue settlement_status y los movimientos. El sandbox crea un QR que no se puede pagar; confirma con POST /sandbox/cashin/{cashin_id}/pay. No hay una transacción bancaria.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents",
                  "payer_tax_number"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "description": "Importe de la solicitud de cobro en CENTAVOS de real, entero (ej.: 15000 = R$ 150,00). Consulta GET /cashin/limits antes de crear; publica los tramos vigentes sin retención y con retención para el pagador.",
                    "examples": [
                      25000
                    ]
                  },
                  "chain": {
                    "type": "string",
                    "default": "polygon",
                    "description": "Red de la ruta de entrega. Usa el network del catálogo en este campo chain."
                  },
                  "asset": {
                    "type": "string",
                    "default": "usdt",
                    "description": "Activo de la ruta disponible para entrega en GET /cashin/catalog; no se limita a stablecoins."
                  },
                  "payout_address": {
                    "type": "string",
                    "description": "Billetera por solicitud de cobro para destino=cripto; si se omite, puede usar settlement_address de la clave. Omitir para destino=saldo. La dirección debe corresponder a la red elegida."
                  },
                  "payer_tax_number": {
                    "type": "string",
                    "description": "CPF (11 dígitos) o CNPJ (14 dígitos) del pagador, solo números. Identifica al pagador y se usa para los límites y las retenciones antifraude publicados por GET /cashin/limits."
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado.",
                    "maxLength": 64
                  },
                  "destino": {
                    "type": "string",
                    "enum": [
                      "cripto",
                      "saldo"
                    ],
                    "default": "cripto",
                    "description": "saldo acredita custodia BRL neta de tarifas, sin billetera. cripto (predeterminado) entrega en la billetera indicada o configurada. Consulta las tarifas/el período de espera en GET /saldo y la retención en la solicitud de cobro/estado."
                  },
                  "customer_ref": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Subcuenta opcional del saldo (el id de tu cliente final). Con `destino: \"saldo\"`, el crédito se abona en esta subcuenta; GET /saldo?customer_ref= lo consulta y POST /payouts con el mismo `customer_ref` lo gasta. Omítela para usar el saldo principal de la clave."
                  },
                  "allow_hold": {
                    "type": "boolean",
                    "default": true,
                    "description": "false rechaza cuando los límites del pagador requieren retención. No elimina otras retenciones/bloqueos de la clave. true u omitido permite la retención aplicable. Consulta held_hours Y hold_hours/liberar_em."
                  },
                  "payout_tag": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Memo/tag del destino. OBLIGATORIO en las redes colectivas —XRP, XLM, TON, ATOM, HBAR, ALGO, EOS, KAVA, LUNA— donde la billetera de destino es compartida y el memo identifica al titular. Sin él, la API responde 400 `memo_obrigatorio` antes de crear cualquier solicitud de cobro. En XRP es la destination tag: entero de 0 a 4294967295. Alias aceptados: `memo`, `tag`, `destination_tag`. El catálogo marca estas rutas con `memoRequired: true`. Alias aceptados: memo, tag, destination_tag."
                  },
                  "payer_name": {
                    "type": "string",
                    "description": "Nombre del pagador, cuando se indica."
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "enum": [
                      "success",
                      "delayed",
                      "held",
                      "expired",
                      "refunded",
                      "failed",
                      "payer_mismatch",
                      "settlement_failed",
                      "settlement_uncertain",
                      "route_unavailable",
                      "provider_unavailable"
                    ],
                    "description": "Solo para una clave de sandbox. GET /sandbox proporciona la matriz de escenarios por flujo. Omitir en producción. Todos los precios, pagos y retiros siguen siendo ficticios."
                  },
                  "delivery_mode": {
                    "type": "string",
                    "enum": [
                      "full",
                      "split"
                    ],
                    "default": "full",
                    "description": "Solo para chain=\"liquid\" (DePix). \"full\" (predeterminado) entrega el DePix directamente a la billetera indicada, por el importe completo: no se descuenta la tarifa de la clave. \"split\" realiza el recorrido de recibir y reenviar: Lunium recibe el DePix, descuenta la tarifa de la clave (fija + porcentaje) y envía el neto a payout_address; net_cents en la respuesta es exactamente lo que recibe el destinatario. En split, payout_address es obligatorio. Sin el campo, se aplica el valor predeterminado de tu clave."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Solicitud de cobro creada: qr_copypaste es el PIX que se debe mostrar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cobranca"
                }
              }
            }
          },
          "403": {
            "description": "Límite del pagador superado (limite_do_pagador) o pagador bloqueado por Lunium para esta integración (pagador_bloqueado: no se crea ninguna solicitud de cobro; no repitas con el mismo CPF/CNPJ).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "400": {
            "description": "Parámetros no válidos, importe fuera de los límites o cash-in no disponible para esta clave. · `valor_abaixo_do_minimo`: la moneda/red elegida tiene un mínimo propio; la respuesta incluye `minimo_estimado_cents` (a partir de qué importe se permite). Se comprueba ANTES de mover dinero. · `memo_obrigatorio`: la red requiere memo/tag y no se ha incluido (o no es válido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "502": {
            "description": "provedor_indisponivel (acao: repetir): el proveedor de liquidación PIX no generó el QR. No se ha creado NINGUNA solicitud de cobro: repite la MISMA llamada (mismo external_id) en unos minutos. Dos errores distintos usan este estado y requieren acciones opuestas: `provedor_indisponivel` (acao `repetir` o `esperar`) es una inestabilidad del liquidador que se resuelve por sí sola; `config_provedor` (acao `falar_com_suporte`) es una configuración no válida en nuestro sistema —la clave PIX, la credencial o la cuenta del proveedor— y NO se resuelve esperando ni repitiendo. En ninguno de los dos casos se crea una solicitud de cobro.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "catalogo_indisponivel / cotacao_indisponivel: la plataforma de intercambio no ofrece una cotización en este momento; repite.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "external_id con diferencias."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-lunium-capability": [
          "pix_to_usdt",
          "pix_to_usdc"
        ],
        "x-lunium-intents": [
          "buy_crypto",
          "onramp",
          "fiat_to_crypto"
        ],
        "x-lunium-reward-eligible": true
      }
    },
    "/keys": {
      "post": {
        "tags": [
          "Cuenta"
        ],
        "operationId": "criarChave",
        "security": [],
        "summary": "Crear clave (autoservicio)",
        "description": "La clave aparece **una sola vez**: guárdala al crearla, solo se almacena el hash. La respuesta también incluye los grupos de seguimiento, donde se anuncian los cambios del contrato antes de publicarse.",
        "responses": {
          "201": {
            "description": "Clave creada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_key": {
                      "type": "string",
                      "description": "La clave en claro: aparece SOLO en esta respuesta (solo guardamos el hash)."
                    },
                    "email_sent": {
                      "type": "boolean",
                      "description": "true cuando se envió una copia de la clave al `email` indicado. false si no se proporcionó correo o falló el envío."
                    },
                    "webhook_secret": {
                      "type": "string",
                      "description": "Presente cuando se indicó `webhook_url`."
                    },
                    "key": {
                      "type": "object",
                      "description": "Vista pública de la clave (prefix, name, flags)."
                    },
                    "limits": {
                      "type": "object",
                      "description": "Límites vigentes."
                    },
                    "monitor_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Monitor en vivo, de solo lectura, del flujo de esta clave."
                    },
                    "lead_attribution": {
                      "type": "object",
                      "description": "Resultado de la atribución cuando se envía un lead_token con consentimiento. Nunca bloquea la creación de la clave.",
                      "required": [
                        "requested",
                        "linked",
                        "status"
                      ],
                      "properties": {
                        "requested": {
                          "type": "boolean",
                          "description": "true si se envió un lead_token en el cuerpo."
                        },
                        "linked": {
                          "type": "boolean",
                          "description": "true si la clave quedó vinculada a un lead con consentimiento."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "nao_solicitado",
                            "vinculado",
                            "token_invalido",
                            "indisponivel"
                          ],
                          "description": "Estado del vínculo."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Campos no válidos (name obligatorio, webhook_url debe ser https pública).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "Límite de creación de claves por IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80,
                    "description": "Nombre del negocio (aparece en el panel y en los avisos)."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Recomendado: la clave recién creada se envía a este correo, además de aparecer en la respuesta."
                  },
                  "settlement_address": {
                    "type": "string",
                    "description": "Billetera EVM (Polygon) de liquidación. Opcional; puede definirse después."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL HTTPS para los eventos. Opcional."
                  },
                  "lead_token": {
                    "type": "string",
                    "pattern": "^ldt_[A-Za-z0-9_-]{43}$",
                    "minLength": 47,
                    "maxLength": 47,
                    "description": "Token opaco `ldt_…` devuelto por POST /leads cuando la persona autorizó el contacto técnico (consentimiento). Vincula esta clave con el lead. Solo en el cuerpo, nunca en la URL. Opcional; su ausencia o un token no válido no impiden la creación."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/keys/me": {
      "get": {
        "tags": [
          "Cuenta"
        ],
        "operationId": "consultarConta",
        "summary": "Límites vigentes y uso del día",
        "description": "Es la cifra que nunca queda desactualizada: lee los límites aquí en lugar de fijarlos en el código. **Cash-out (venta de cripto):** de R$ 6,00 a R$ 250.000,00 por transacción, más un límite diario de R$ 100.000,00 por CPF/CNPJ de quien RECIBE el PIX (por clave, cuando la clave PIX no es un documento), que se renueva a medianoche, hora de Brasilia. El máximo efectivo es el MENOR de ambos y se devuelve en `limits.max_brl_cents`; el máximo por transacción se devuelve en `limits.max_brl_cents_por_transacao`. No existe un límite diario por clave de API para la venta. **Cash-in y payouts:** tampoco hay un límite diario por clave (desde el 10/09/2026): `limits.daily_limit_cents` se devuelve `null`, `limits.tier` se devuelve `\"Sem teto\"`, `limits.available_today_cents` y `limits.next_tier` se devuelven `null` y `limits.daily_limit_applies_to` se devuelve `[]`. Cada solicitud de cobro va de R$ 1,00 a R$ 6.000,00 (mínimo efectivo en `limits.per_operation.cashin.min_brl_cents`) y pasa por las reglas del pagador (`GET /cashin/limits`). El único límite diario por clave posible es el que la propia clave define en `mandate.max_diario_cents`.",
        "responses": {
          "200": {
            "description": "Tu clave y tus límites.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChaveMe"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Actualiza la clave (nombre, settlement, webhook, rotaciones)",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80
                  },
                  "settlement_address": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Dirección Polygon 0x…; null la borra."
                  },
                  "webhook_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "https pública; null la borra. Al definirla, se genera webhook_secret si la clave aún no lo tiene."
                  },
                  "rotate_webhook_secret": {
                    "type": "boolean",
                    "description": "true rota el secreto del webhook: aparece UNA sola vez en la respuesta."
                  },
                  "rotate_monitor_token": {
                    "type": "boolean",
                    "description": "true rota el token del monitor: la URL anterior deja de mostrar datos a partir de esta llamada; la nueva se devuelve en monitor_url."
                  },
                  "partner_fee_bps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Comisión adicional del socio en bps, que se suma a la tarifa de Lunium y paga el usuario final (100 = 1%; máximo 1000 = 10%). Se aplica a las solicitudes de cobro NUEVAS: las abiertas mantienen su tarifa congelada. 0 la desactiva."
                  },
                  "partner_cashout_fee_bps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Comisión adicional del socio en la VENTA (cripto -> PIX), en puntos básicos, POR ENCIMA de la tarifa de Lunium. Se congela en cada orden al crearla; se aplica a las órdenes nuevas. No se aplica a la venta mediante QR Copia y Pega. 0 la desactiva."
                  },
                  "partner_saque_fee_bps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "Comisión adicional del socio en la SALIDA DE CUSTODIA (retiro mediante PIX en POST /payouts y retiro en cripto en POST /saldo/sacar-cripto), en puntos básicos, debitada del saldo POR ENCIMA de la tarifa de Lunium. Se acredita cuando se completa el retiro. 0 la desactiva."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Clave actualizada. Puede incluir webhook_secret (una sola vez) y una nueva monitor_url."
          },
          "400": {
            "description": "Campos no válidos o nada que actualizar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "updateMyKey"
      }
    },
    "/ping": {
      "get": {
        "tags": [
          "Cuenta"
        ],
        "operationId": "ping",
        "security": [],
        "summary": "Estado de la API",
        "responses": {
          "200": {
            "description": "pong"
          }
        }
      }
    },
    "/keys/sandbox": {
      "post": {
        "summary": "Obtener una clave de API de sandbox: una llamada, sin necesidad de clave de API",
        "description": "Devuelve una clave lun_test_ en una llamada: sin aprobación, sin clave de API y sin billetera. `email` es obligatorio: el correo de la persona que hará las pruebas. Aproximadamente un minuto después, el soporte de LuniumPay envía a esa dirección un mensaje que explica qué es LuniumPay, la integración en 3 pasos, el manual y el PDF, el diagrama de flujo y VendaCripto (una aplicación lista para comprar o vender cripto con PIX, sin integración). Un mensaje por dirección, con enlace para darse de baja. Si falta el correo o no es válido: 400 email_obrigatorio (acao=corrigir, campo=email). Los seis recorridos financieros se simulan con fondos ficticios mediante los endpoints habituales. GET /sandbox devuelve los flujos compatibles, la matriz de escenarios y los controles de simulación. POST /sandbox/cashin/{cashin_id}/pay confirma una solicitud de cobro de prueba que no admite pagos. Cash-in, custodia y payouts son persistentes; la retención de cash-out es de dos horas. Los webhooks firmados usan el sistema habitual de entrega con sandbox:true. No se llama a ningún proveedor financiero. Los catálogos y precios son instantáneas sintéticas, no cotizaciones en vivo. Consulta https://docs.luniumpay.com/sandbox .",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 160,
                    "description": "Obligatorio. Correo electrónico de la persona que hará las pruebas, p. ej., you@company.com. El soporte de LuniumPay envía a esa dirección un mensaje con la guía de integración (qué es LuniumPay, los 3 pasos, manual y PDF, diagrama de flujo, VendaCripto). Un mensaje por dirección, con un enlace para darse de baja."
                  },
                  "name": {
                    "type": "string",
                    "description": "Etiqueta opcional para reconocer la clave más adelante."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Webhook HTTPS opcional."
                  },
                  "lead_token": {
                    "type": "string",
                    "pattern": "^ldt_[A-Za-z0-9_-]{43}$",
                    "description": "Token opaco opcional devuelto por POST /leads con consentimiento. Vincula esta clave de PRUEBA con el contacto. Una atribución no válida o no disponible nunca bloquea la creación de la clave. Nunca incluyas este token en una URL ni en un registro."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Clave de sandbox creada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_key": {
                      "type": "string",
                      "example": "lun_test_1df82296e3459819702c6a6087aab1c7"
                    },
                    "sandbox": {
                      "type": "boolean",
                      "const": true
                    },
                    "gatilhos": {
                      "type": "object",
                      "description": "Los activadores deterministas descritos anteriormente."
                    },
                    "diferencas_para_producao": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "lead_link": {
                      "type": "object",
                      "properties": {
                        "requested": {
                          "type": "boolean"
                        },
                        "linked": {
                          "type": "boolean"
                        },
                        "status": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "email_obrigatorio: falta el correo electrónico o no es válido. Envía el correo de la persona que hará las pruebas, p. ej., {\"email\": \"you@company.com\"}.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                },
                "example": {
                  "erro": "email_obrigatorio",
                  "acao": "corrigir",
                  "campo": "email",
                  "detail": "Informe o e-mail de quem vai testar: {\"email\": \"voce@empresa.com\"}. É por ele que mandamos o manual, o fluxograma e o passo a passo da integração."
                }
              }
            }
          },
          "429": {
            "description": "Demasiadas claves desde esta IP hoy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "createSandboxKey"
      }
    },
    "/cashin/limits": {
      "get": {
        "summary": "Cuánto puede pagar este contribuyente ahora",
        "description": "Consulta orientativa de los límites por CPF/CNPJ, el uso y los tramos sin retención/con retención. La creación vuelve a validar la operación y las condiciones de la clave, incluida la custodia sin período de espera. max_amount_cents no sustituye a los mínimos de tarifa, ruta/proveedor ni a las comprobaciones contractuales. La retención puede producirse en el proveedor o localmente; consulta held_hours, hold_hours y liberar_em en la solicitud de cobro. No fijes los límites en el cliente.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "payer_tax",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^([0-9]{11}|[0-9]{14})$"
            },
            "description": "CPF (11 dígitos) o CNPJ (14 dígitos), solo números."
          }
        ],
        "responses": {
          "200": {
            "description": "Estado actual de los tramos",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payer_tax": {
                      "type": "string",
                      "description": "Se devuelve enmascarado, nunca completo."
                    },
                    "stage": {
                      "enum": [
                        "first_transaction",
                        "first_24h",
                        "mature",
                        "disabled",
                        "desconhecido"
                      ]
                    },
                    "max_amount_cents": {
                      "type": "integer",
                      "description": "Rango máximo orientativo del documento, incluida una eventual retención; la creación vuelve a validar la clave, los mínimos y la disponibilidad."
                    },
                    "used_cents": {
                      "type": "integer"
                    },
                    "available_cents": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Lo que aún puede procesarse sin retención en la etapa actual. Alias: instant_available_cents. Null cuando la regla de límite está desactivada (stage=disabled)."
                    },
                    "limit_cents": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": " Null cuando la regla de límite está desactivada (stage=disabled)."
                    },
                    "next_stage": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "Cuándo aumenta el límite y a cuánto."
                    },
                    "instant_available_cents": {
                      "type": "integer",
                      "description": "Igual que available_cents: lo que se procesa sin retención, expresado explícitamente."
                    },
                    "held_qr": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "Condiciones del rango con retención cuando corresponda. El proveedor puede retener el importe o la solicitud de cobro puede aplicar una retención local. Comprueba la respuesta de creación/estado.",
                      "properties": {
                        "stage": {
                          "type": "string",
                          "enum": [
                            "held_qr"
                          ]
                        },
                        "max_amount_cents": {
                          "type": "integer"
                        },
                        "used_cents": {
                          "type": "integer",
                          "description": "Pagado + en curso en las últimas 24h."
                        },
                        "available_cents": {
                          "type": "integer"
                        },
                        "hold_hours": {
                          "type": "integer"
                        },
                        "explicacao": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Documento con formato incorrecto",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "getCashinLimits"
      }
    },
    "/cashin/{cashin_id}/status": {
      "get": {
        "summary": "Estado de una solicitud de cobro PIX",
        "description": "Consulta por separado el estado del PIX y del abono/entrega. paid por sí solo no significa criptomonedas entregadas ni saldo disponible. settlement_status=sent completa el abono/entrega; en custodia, comprueba el saldo disponible/bloqueado. delayed representa una retención del proveedor; paid con liberar_em puede estar sujeto a una retención local. No pidas otro pago porque la entrega aún no se haya completado. Prioriza el webhook; el polling debe respetar el límite de solicitudes de la clave.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "cashin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estado actual con una cronología marcada por el servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusCobranca"
                }
              }
            }
          },
          "404": {
            "description": "No encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "getPixChargeStatus"
      }
    },
    "/payouts": {
      "post": {
        "summary": "Enviar un PIX directamente (sin etapa de cripto)",
        "description": "Envía PIX debitando únicamente el saldo BRL disponible de la cuenta principal o de la subcuenta customer_ref, recibido mediante PIX. Consulta payout.enabled en GET /keys/me, custodia_ativa, pix_rules y las tarifas en GET /saldo. Máximo R$ 6.000,00 por PIX, sujeto a límites menores de la cuenta. Es obligatorio el CPF/CNPJ válido del destinatario; la API puede obtenerlo de una clave CPF/CNPJ. El importe más las tarifas se reservan antes de llamar al proveedor; sin saldo, 402. Consulta la tarifa vigente en la API y concilia fee_cents de la operación. Siguen siendo aplicables los límites y el mandate de la clave. Usa un external_id estable y consulta la orden original después de un timeout. El sandbox usa saldo ficticio y calcula la tarifa publicada por la API; no hay pagos reales. La billetera USDT es independiente del saldo BRL: requiere la habilitación del proyecto, recibe depósitos externos de USDT y no usa /payouts. Cuando está habilitada, usa funding_source=crypto_usdt; en este flujo no se exige el documento del destinatario. Sus límites proceden de la cotización y las condiciones de la API, no del límite de R$ 6.000 del saldo BRL. No está disponible en sandbox.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Importe del PIX en CENTAVOS de real brasileño, entero (5000 = R$ 50,00). Máximo 600000 (R$ 6.000,00), sujeto a un límite menor de la cuenta. Las tarifas se debitan además de este importe.",
                    "maximum": 600000
                  },
                  "pix_key": {
                    "type": "string",
                    "description": "Clave PIX de destino que recibe los reales brasileños (CPF, CNPJ, teléfono +55, correo electrónico o clave aleatoria). Con 11 dígitos sin formato, envía también pix_key_type (\"cpf\" o \"phone\"); sin él, la API rechaza con erro=tipo_ambiguo en lugar de adivinar."
                  },
                  "pix_key_type": {
                    "enum": [
                      "cpf",
                      "cnpj",
                      "phone",
                      "email",
                      "random"
                    ],
                    "description": "Opcional: se deduce del formato de la clave (correo, CNPJ, UUID o teléfono con +55). Solo es obligatorio cuando la clave tiene 11 dígitos puros, donde CPF y teléfono son indistinguibles; en ese caso, la API rechaza con el error tipo_ambiguo en lugar de adivinar."
                  },
                  "tax_number": {
                    "type": "string",
                    "description": "CPF o CNPJ válido del destinatario, con los dígitos de control verificados. Obligatorio para claves de correo electrónico, teléfono o aleatorias. Para una clave CPF/CNPJ válida, puede omitirse: la API usa el documento de la propia clave; si se indica, debe coincidir. No demuestra la titularidad de la clave."
                  },
                  "beneficiary_name": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Opcional. Nombre completo del beneficiario, que se envía al proveedor PIX como nombre del usuario final. No es obligatorio: se permiten payouts a claves PIX de terceros."
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Identificador idempotente de hasta 64 caracteres. En los reintentos, conserva el importe, la clave PIX, el tipo, el documento, customer_ref y funding_source de la solicitud original. Un conflicto 409 external_id_divergente o external_id_nao_verificavel devuelve payout_id/recovery_endpoint para consultar la orden original; no generes otro ID solo para eludir el conflicto.",
                    "maxLength": 64
                  },
                  "customer_ref": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Subcuenta que se debitará (claves de custodia). Se debita ANTES de enviar el PIX: importe + tarifa de la cuenta principal (`saque_fee_bps`) + tarifa del proveedor; ante un rechazo explícito del proveedor, se revierten los débitos. 402 `saldo_insuficiente` cuando el saldo disponible < importe + tarifas (`saque_fee_bps`, `saque_taxa_estimada_cents` en GET /saldo). Subcuenta (p. ej., el comercio) cuyo saldo se debita. El mismo valor usado en el depósito."
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "enum": [
                      "success",
                      "delayed",
                      "held",
                      "expired",
                      "refunded",
                      "failed",
                      "payer_mismatch",
                      "settlement_failed",
                      "settlement_uncertain",
                      "route_unavailable",
                      "provider_unavailable"
                    ],
                    "description": "Solo para una clave de sandbox. GET /sandbox proporciona la matriz de escenarios por flujo. Omitir en producción. Todos los precios, pagos y retiros siguen siendo ficticios."
                  },
                  "funding_source": {
                    "type": "string",
                    "enum": [
                      "pix_brl"
                    ],
                    "description": "Opcional. Único valor aceptado: pix_brl. Este endpoint debita el saldo en reales brasileños recibido mediante PIX; nunca debita la billetera USDT."
                  }
                },
                "required": [
                  "amount_cents",
                  "pix_key"
                ]
              }
            }
          }
        },
        "responses": {
          "403": {
            "description": "Interruptor administrativo de emergencia o `custodia_desligada`. Las claves de producción están habilitadas por defecto; si aparece esta respuesta, detente y contacta con soporte en lugar de reintentar. No se envió ningún PIX.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "external_id_divergente o external_id_nao_verificavel: consulta payout_id/recovery_endpoint de la operación original. No cambies los parámetros ni generes un nuevo ID para la misma intención. em_processamento: consulta la orden en curso sin reenviar un nuevo pago.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Erro"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "payout_id": {
                          "type": "string",
                          "description": "Identificador del payout original."
                        },
                        "recovery_endpoint": {
                          "type": "string",
                          "description": "Ruta relativa de la API del payout original."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "423": {
            "description": "carencia_primeiro_deposito — período de espera del primer depósito (solo claves con un período de espera contractual; ninguno por defecto desde 2026-09-16): no se permiten retiros de esta subcuenta hasta `libera_em`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "erro": {
                      "type": "string",
                      "enum": [
                        "carencia_primeiro_deposito"
                      ]
                    },
                    "acao": {
                      "type": "string",
                      "enum": [
                        "esperar"
                      ]
                    },
                    "detail": {
                      "type": "string"
                    },
                    "libera_em": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "saque_indisponivel: financiación/proveedor no disponible; en este intento no se realiza ninguna reserva ni débito nuevo. idempotencia_indisponivel: no se pudo comprobar la orden anterior; no se crea ninguna orden nueva, pero la anterior puede existir. Espera y consulta el mismo external_id; no generes otro ID."
          },
          "200": {
            "description": "Payout creado o repetición idempotente de la operación original.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payout"
                }
              }
            }
          },
          "400": {
            "description": "Rechazo o fallo; lee erro, acao y detail cuando estén presentes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "402": {
            "description": "Rechazo o fallo; lee erro, acao y detail cuando estén presentes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "500": {
            "description": "Rechazo o fallo; lee erro, acao y detail cuando estén presentes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "createPixPayout"
      },
      "get": {
        "summary": "Enumera los payouts de esta clave",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "processing",
                "sent",
                "failed",
                "refunded"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "description": "Recuperación idempotente: devuelve la operación con este external_id (0 o 1). Único por clave y producto, distingue mayúsculas y minúsculas y se conserva de forma permanente."
          }
        ],
        "responses": {
          "200": {
            "description": "Lista (más recientes primero). Lista vacía = 200, nunca 403.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payouts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payout"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Payout aún no habilitado para esta clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "listPixPayouts"
      }
    },
    "/payouts/{payout_id}": {
      "get": {
        "summary": "Estado de un payout",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "payout_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estado del retiro.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payout"
                }
              }
            }
          },
          "404": {
            "description": "No encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "getPixPayout"
      }
    },
    "/webhooks/deliveries": {
      "get": {
        "summary": "Historial de entregas de webhook de esta clave",
        "description": "Diagnóstico de lo enviado, lo que falló y por qué. No devuelve el cuerpo del evento; para reenviar el cuerpo original, usa el reintento.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "sent",
                "failed"
              ]
            }
          },
          {
            "name": "event",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "cashin.paid",
                "cashin.delayed",
                "cashin.held",
                "cashin.settled",
                "cashin.settlement_failed",
                "cashin.expired",
                "cashin.refunded",
                "cashin.failed",
                "cashout.awaiting_deposit",
                "cashout.deposit_detected",
                "cashout.confirming",
                "cashout.processing",
                "cashout.under_review",
                "cashout.awaiting_refund_address",
                "cashout.refunding",
                "cashout.completed",
                "cashout.receipt_ready",
                "cashout.refunded",
                "cashout.expired",
                "cashout.failed",
                "payout.sent",
                "payout.failed",
                "payout.refunded",
                "webhook.test",
                "saldo.liberado",
                "saldo.congelado",
                "saldo.transferido",
                "wallet.deposit_credited",
                "wallet.payment_completed",
                "wallet.payment_failed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Entregas, más recientes primero.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EntregaWebhook"
                      }
                    },
                    "failed_count": {
                      "type": "integer",
                      "description": "Cuántas de las entregas de la respuesta agotaron los intentos."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Filtro no válido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "listWebhookDeliveries"
      }
    },
    "/webhooks/deliveries/{event_id}/retry": {
      "post": {
        "summary": "Reenviar un evento",
        "description": "Intenta entregarlo durante la propia llamada y responde con el resultado. Si vuelve a fallar, la entrega regresa a la cola con 12 intentos nuevos. Rechaza el reenvío de lo ya confirmado con 2xx.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Entregado ahora.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event_id": {
                      "type": "string"
                    },
                    "delivered": {
                      "type": "boolean",
                      "const": true
                    },
                    "status_code": {
                      "type": "integer"
                    },
                    "ms": {
                      "type": "integer"
                    },
                    "delivery_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "No se entregó ahora; se volvió a poner en cola."
          },
          "404": {
            "description": "No encontrado para esta clave",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Ya entregado: reenviarlo lo duplicaría",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "retryWebhookDelivery"
      }
    },
    "/webhooks/test": {
      "post": {
        "summary": "Emitir un evento de prueba ahora",
        "description": "Envía un `webhook.test` a tu webhook_url mediante el MISMO transporte de producción y devuelve lo que respondió tu endpoint (estado y latencia). No se mueve dinero ni se añade nada a la cola. Úsalo antes de activar la primera solicitud de cobro real. Máximo de 6 por minuto.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tu endpoint respondió 2xx.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "event_id": {
                      "type": "string"
                    },
                    "delivery_id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "status_code": {
                      "type": "integer"
                    },
                    "ms": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "webhook_url no configurada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "Más de 6 pruebas por minuto",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "502": {
            "description": "Tu endpoint no respondió 2xx: el cuerpo indica exactamente qué ocurrió.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "testWebhook"
      }
    },
    "/cashin/charges": {
      "get": {
        "summary": "Lista/recupera solicitudes de cobro de cash-in de esta clave",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "external_id",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "description": "Recuperación idempotente: devuelve la operación con este external_id (0 o 1). Único por clave y producto, distingue mayúsculas y minúsculas y se conserva de forma permanente."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "end",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista (las más recientes primero).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "charges": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Cobranca"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente/no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "La consulta de la lista requiere X-API-Key (no es pública).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "listPixCharges"
      }
    },
    "/cashin/preview": {
      "post": {
        "summary": "Cotización de cash-in: no crea nada",
        "description": "Política del 15/10/2026: el depósito en saldo cuesta R$ 1,00, sin porcentaje ni comisión. La compra directa cuesta 3,3% + R$ 1,00; la conversión de saldo a cripto cuesta 3,3%, sin una nueva parte fija; el retiro Pix del saldo cuesta 1,5%. La comisión del socio se añade a las tarifas de compra y salida. Cotización de referencia: ask de Binance, sin recargo. Los costes de red y procesamiento, cuando correspondan, aparecen en la vista previa. Con destino=saldo, la vista previa devuelve BRL: net_cents=amount_cents-100; sin conversión. No crea una solicitud de cobro. No es la vista previa del débito de un retiro en cripto.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Importe BRL en centavos enteros. El mínimo efectivo depende de la clave, las tarifas y la ruta. Consulta GET /keys/me y min_brl_cents/limits devueltos; no fijes el mínimo del ejemplo."
                  },
                  "asset": {
                    "type": "string",
                    "default": "usdt",
                    "description": "Activo de la ruta disponible para entrega en GET /cashin/catalog; no se limita a stablecoins."
                  },
                  "chain": {
                    "type": "string",
                    "default": "polygon",
                    "description": "Red de la ruta de entrega. Usa el network del catálogo en este campo chain."
                  },
                  "delivery_mode": {
                    "type": "string",
                    "enum": [
                      "full",
                      "split"
                    ],
                    "default": "full",
                    "description": "Solo para chain=\"liquid\" (DePix). \"full\" (predeterminado) entrega el DePix directamente a la billetera indicada, por el importe completo: no se descuenta la tarifa de la clave. \"split\" realiza el recorrido de recibir y reenviar: Lunium recibe el DePix, descuenta la tarifa de la clave (fija + porcentaje) y envía el neto a payout_address; net_cents en la respuesta es exactamente lo que recibe el destinatario. En split, payout_address es obligatorio. Sin el campo, se aplica el valor predeterminado de tu clave."
                  },
                  "destino": {
                    "type": "string",
                    "enum": [
                      "cripto",
                      "saldo"
                    ],
                    "default": "cripto"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cotización con la tarifa de la clave aplicada.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "asset": {
                          "type": "string",
                          "description": "Activo de entrega, repetido de la solicitud (usdt, usdc, depix, btc…)."
                        },
                        "amount_cents": {
                          "type": "integer",
                          "description": "Importe de la solicitud de cobro en centavos, repetido de la solicitud."
                        },
                        "admin_fee_bps": {
                          "type": "integer"
                        },
                        "admin_fee_fixed_cents": {
                          "type": "integer"
                        },
                        "fee_total_cents": {
                          "type": "integer",
                          "description": "TODO lo descontado del bruto: tarifa fija + % de Lunium + comisión adicional del socio. Invariante: fee_total_cents + net_cents == amount_cents. Para saber a quién corresponde cada parte, lee lunium_fee_cents y partner_fee_cents."
                        },
                        "net_cents": {
                          "type": "integer",
                          "description": "Importe neto convertido a cripto para el usuario final, ya descontada la comisión adicional del socio (si existe)."
                        },
                        "brl_per_usdt": {
                          "type": "string",
                          "description": "Cotización redondeada para su lectura: el importe entregado usa la cotización completa."
                        },
                        "usdt_amount": {
                          "type": "string",
                          "description": "Campo antiguo. En la vía de la plataforma (DePix y entregas mediante la propia billetera de Lunium) es la cantidad entregada; cuando la entrega pasa por conversión (BTC, ETH y demás pares del catálogo, incluidas stablecoins en algunas rutas), es el USDT usado en la compra, NO lo que recibe el cliente. Para mostrar la cripto que llega a la billetera, lee siempre asset_amount."
                        },
                        "chain": {
                          "type": "string",
                          "description": "Red de entrega, repetida de la solicitud (normalizada: sol → solana, trc20 → tron…)."
                        },
                        "asset_amount": {
                          "type": "string",
                          "description": "Cantidad de cripto que llega a la billetera del cliente, ya descontadas la tarifa de la clave, la comisión adicional del socio y, en las rutas con conversión, la comisión de compra y la tarifa de retiro de la red (withdraw_fee). Es la cifra que debe mostrarse como “recibes”. Mismo campo que en sandbox. Estimación: la entrega recalcula la cotización al pagar."
                        },
                        "withdraw_fee": {
                          "type": "string",
                          "description": "Tarifa de retiro de la red, en unidades del activo, ya descontada de asset_amount. Es fija por envío (no depende del importe), por lo que pesa más en importes pequeños, por ejemplo, BTC en la red Bitcoin. \"0\" en la vía de la plataforma. En reales brasileños: withdraw_fee × brl_per_asset."
                        },
                        "withdraw_min": {
                          "type": "string",
                          "description": "Menor cantidad que envía la red, en unidades del activo (rutas con conversión). El mínimo en reales brasileños ya se devuelve calculado en min_brl_cents."
                        },
                        "brl_per_asset": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "Reales brasileños por unidad del activo en esta vista previa (importe neto ÷ cantidad comprada). Sirve para convertir withdraw_fee y asset_amount a reales brasileños. Informativo; null cuando no hay cálculo."
                        },
                        "min_brl_cents": {
                          "type": "integer",
                          "description": "Menor importe, en centavos, que entrega esta ruta con las tarifas de esta clave."
                        },
                        "eta": {
                          "type": "string",
                          "description": "Plazo habitual de entrega en esta ruta (rutas con conversión); no es un plazo máximo contractual."
                        },
                        "amount": {
                          "type": "string",
                          "description": "Nombre anterior de asset_amount (solo en las rutas con conversión). Prefiere asset_amount.",
                          "deprecated": true
                        },
                        "network_min": {
                          "type": "string",
                          "description": "Nombre anterior de withdraw_min. Prefiere withdraw_min.",
                          "deprecated": true
                        },
                        "partner_fee_bps": {
                          "type": "integer",
                          "description": "Comisión adicional del socio aplicada en esta cotización (bps). 0 = no se usa."
                        },
                        "lunium_fee_cents": {
                          "type": "integer",
                          "description": "Parte de Lunium (fija + %). Sin comisión adicional, es igual a fee_total_cents."
                        },
                        "partner_fee_cents": {
                          "type": "integer",
                          "description": "Parte del socio (comisión adicional), acreditada en la comisión cuando se entrega la cripto. Residuo de un único floor: la parte de Lunium no cambia con la comisión adicional."
                        },
                        "sandbox": {
                          "const": false
                        },
                        "delivery_mode": {
                          "type": "string",
                          "enum": [
                            "full",
                            "split"
                          ],
                          "description": "Solo en chain=\"liquid\": cómo se entregó el DePix. Ausente en las demás redes."
                        },
                        "destino": {
                          "type": "string",
                          "enum": [
                            "cripto",
                            "saldo"
                          ]
                        }
                      },
                      "description": "Política del 15/10/2026: el depósito en saldo cuesta R$ 1,00, sin porcentaje ni comisión. La compra directa cuesta 3,3% + R$ 1,00; la conversión de saldo a cripto cuesta 3,3%, sin una nueva parte fija; el retiro Pix del saldo cuesta 1,5%. La comisión del socio se añade a las tarifas de compra y salida. Cotización de referencia: ask de Binance, sin recargo. Los costes de red y procesamiento, cuando correspondan, aparecen en la vista previa. Con destino=saldo, la vista previa devuelve BRL: net_cents=amount_cents-100; sin conversión. No crea una solicitud de cobro. No es la vista previa del débito de un retiro en cripto."
                    },
                    {
                      "type": "object",
                      "description": "Sandbox aislado: cotización sintética con tarifa de retiro de la ruta, sin llamada a un proveedor. fee_bps y fee_fixed_cents son tarifas de simulación; no representan una cotización de producción.",
                      "required": [
                        "sandbox",
                        "synthetic",
                        "amount_cents",
                        "min_brl_cents",
                        "fee_bps",
                        "fee_fixed_cents",
                        "partner_fee_bps",
                        "asset",
                        "chain",
                        "usdt_amount",
                        "asset_amount",
                        "withdraw_fee",
                        "withdraw_min",
                        "brl_per_usdt",
                        "brl_per_asset"
                      ],
                      "properties": {
                        "sandbox": {
                          "const": true
                        },
                        "synthetic": {
                          "const": true
                        },
                        "amount_cents": {
                          "type": "integer"
                        },
                        "min_brl_cents": {
                          "type": "integer"
                        },
                        "fee_bps": {
                          "type": "integer"
                        },
                        "fee_fixed_cents": {
                          "type": "integer"
                        },
                        "partner_fee_bps": {
                          "type": "integer"
                        },
                        "asset": {
                          "type": "string"
                        },
                        "chain": {
                          "type": "string"
                        },
                        "usdt_amount": {
                          "type": "string"
                        },
                        "asset_amount": {
                          "type": "string"
                        },
                        "withdraw_fee": {
                          "type": "string"
                        },
                        "withdraw_min": {
                          "type": "string"
                        },
                        "brl_per_usdt": {
                          "type": "number"
                        },
                        "brl_per_asset": {
                          "type": "number"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Importe fuera de los límites de la clave o parámetros no válidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        },
        "operationId": "previewPixCharge"
      }
    },
    "/pix/keys/lookup": {
      "get": {
        "operationId": "consultarTitularChavePix",
        "summary": "Consultar el titular PIX cuando la verificación esté disponible",
        "description": "Consulta auxiliar del titular. Cuando está deshabilitada, devuelve HTTP 200 con verified=false, available=false, verification_status=not_performed, source=disabled y los datos del titular nulos. Esto no deshabilita los pagos. Cuando está disponible, devuelve datos obtenidos del DICT sujetos a caché y límites de frecuencia. El sandbox devuelve un titular ficticio, source=sandbox. No interpretes HTTP 200 por sí solo como verificación del titular; envía type explícito cuando conozcas el tipo.",
        "tags": [
          "Pix"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "La clave PIX (CPF, CNPJ, correo electrónico, teléfono con o sin +55, o aleatoria).",
            "examples": {
              "email": {
                "value": "vendas@loja.com.br"
              },
              "telefone": {
                "value": "+5511987654321"
              }
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "cpf",
                "cnpj",
                "phone",
                "email",
                "random"
              ]
            },
            "description": "Opcional. Se deduce del formato cuando no se indica."
          }
        ],
        "responses": {
          "200": {
            "description": "Titular encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TitularPix"
                }
              }
            }
          },
          "400": {
            "description": "Clave con formato no válido (`pix_key_invalida`) o ausente (`pix_key_obrigatoria`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "La clave no existe en el DICT (`chave_nao_encontrada`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "Límite de 5 consultas/min de la cuenta (`limite_consultas`); lee `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "Proveedor DICT no disponible (`provedor_indisponivel`, repetir) o consulta deshabilitada (`consulta_indisponivel`, esperar).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/saldo": {
      "get": {
        "tags": [
          "Cuenta"
        ],
        "summary": "Saldo BRL (custodia): disponible, retenido y próximas liberaciones",
        "description": "Saldo BRL de la cuenta principal o de la subcuenta customer_ref. Devuelve el disponible, el bloqueado, las próximas liberaciones y las condiciones efectivas de custodia. Las tarifas y el período de espera dependen de la clave. La retención local de la solicitud de cobro, la retención del proveedor y el período de espera del saldo son reglas distintas. Solo disponivel_cents financia retiros; GET /saldo/consolidado suma la cuenta principal y los clientes. El sandbox devuelve saldo ficticio persistente; admite depósitos simulados, retiros y transferencias.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "customer_ref",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "description": "Subcuenta (el identificador de tu cliente final). Omítela para consultar el saldo principal de la clave."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "disponivel_cents",
                    "bloqueado_cents",
                    "total_cents"
                  ],
                  "properties": {
                    "customer_ref": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "maxLength": 80
                    },
                    "disponivel_cents": {
                      "type": "integer"
                    },
                    "bloqueado_cents": {
                      "type": "integer"
                    },
                    "total_cents": {
                      "type": "integer"
                    },
                    "movimentos": {
                      "type": "integer"
                    },
                    "proximas_liberacoes": {
                      "type": "array",
                      "description": "Próximas liberaciones del ámbito solicitado (cuenta principal o customer_ref). Puede incluir hasta 200 elementos (antes de la 1.44.1, como máximo 20): no presupongas un límite menor.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "disponivel_em": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "valor_cents": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "custodia_ativa": {
                      "type": "boolean",
                      "description": "false = esta clave no puede mantener BRL (se rechaza destino \"saldo\")."
                    },
                    "carencia_horas": {
                      "type": "integer",
                      "description": "Período de espera configurado para esta clave; cero cuando el crédito entra en el saldo sin período de espera. Las retenciones de la solicitud de cobro y los créditos bloqueados siguen siendo independientes."
                    },
                    "deposito_fee_bps": {
                      "type": "integer",
                      "description": "Siempre 0 para los depósitos nuevos en saldo."
                    },
                    "saque_taxa_estimada_cents": {
                      "type": "integer",
                      "description": "Tarifa fija o mínimo estimado del proveedor. Para el porcentaje, aplica saque_taxa_provedor_formula; no es el precio total de todos los retiros."
                    },
                    "saque_fee_bps": {
                      "type": "integer",
                      "description": "Tarifa Lunium del retiro Pix del saldo; predeterminado 150 bps, más la comisión del socio. Procesamiento indicado por separado."
                    },
                    "saque_cripto_fee_bps": {
                      "type": "integer",
                      "description": "Recargo en el débito de cripto: 0. La tarifa Lunium se aplica una sola vez en la conversión."
                    },
                    "primeiro_deposito_em": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "Cuándo se acreditó el primer depósito de esta subcuenta (null = nunca ha depositado)."
                    },
                    "carencia_ate": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "Fin del período de espera del primer depósito, cuando está en curso; null en caso contrario. Lee también bloqueado_cents y proximas_liberacoes."
                    },
                    "retencao_acima_cents": {
                      "type": "integer",
                      "description": "Umbral de la política para el primer pago elegible en custodia. No significa que se retengan todos los depósitos superiores a este importe; las reglas y la clave también intervienen."
                    },
                    "deposito_fee_fixed_cents": {
                      "type": "integer",
                      "description": "Siempre 100 centavos por cada depósito nuevo en saldo."
                    },
                    "saque_taxa_provedor_formula": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Fórmula vigente: fija (piso_cents) o porcentual con mínimo. No fijes un proveedor como siempre activo."
                    },
                    "saque_taxa_provedor_tipo": {
                      "type": "string",
                      "enum": [
                        "fixo",
                        "percentual"
                      ],
                      "description": "Tipo vigente de tarifa del proveedor de payout."
                    },
                    "saque_taxa_provedor_piso_cents": {
                      "type": "integer",
                      "description": "Tarifa fija o mínimo de la tarifa porcentual, en centavos."
                    },
                    "sandbox": {
                      "type": "boolean",
                      "description": "true en la respuesta reducida de prueba."
                    },
                    "saque_partner_fee_bps": {
                      "type": "integer",
                      "description": "Comisión adicional del socio en la salida (PIX y cripto), por encima de la tarifa de Lunium."
                    },
                    "saque_fee_total_bps": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Tarifa de servicio única que se muestra al cliente: tarifa de la cuenta principal más comisión adicional del socio, en bps (250 = 2.5%). Muéstrala junto con la tarifa fija, sin una comisión del socio por separado. Usa los importes monetarios de tarifas realmente cotizados/guardados; los componentes internos se redondean a centavos de forma independiente. Producción y sandbox."
                    },
                    "saque_cripto_conversao_fee_bps": {
                      "type": "integer",
                      "description": "Porcentaje Lunium en la conversión de saldo a cripto, sobre la cotización Binance sin recargo; predeterminado 330 bps."
                    },
                    "saque_cripto_conversao_fee_fixed_cents": {
                      "type": "integer",
                      "description": "Cero: el coste de entrada ya se cobró en el depósito."
                    },
                    "deposito_partner_fee_bps": {
                      "type": "integer",
                      "description": "Cero: el depósito en saldo no genera comisión del socio."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida"
          }
        },
        "operationId": "getBalance"
      }
    },
    "/saldo/extrato": {
      "get": {
        "tags": [
          "Cuenta"
        ],
        "summary": "Movimientos del saldo: asientos del ledger u operaciones agrupadas",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "customer_ref",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "visao",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "lancamentos",
                "operacoes"
              ],
              "default": "lancamentos"
            },
            "description": "operacoes agrupa las tarifas relacionadas dentro de la operación; omitirlo conserva el contrato del ledger sin agrupar."
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,18}$"
            },
            "description": "Usa proxima_pagina de la misma vista y customer_ref. Cadena decimal bigint; no la conviertas a Number. La vista agrupada se ancla al ID más antiguo del ledger."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "movimentos": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "valor_cents": {
                            "type": "integer",
                            "description": "Efecto total con signo sobre el saldo BRL en centavos. Débito negativo, crédito positivo. La vista agrupada ya incluye las tarifas."
                          },
                          "sentido": {
                            "type": "string",
                            "enum": [
                              "credito",
                              "debito"
                            ]
                          },
                          "tipo": {
                            "type": "string",
                            "enum": [
                              "cashin",
                              "payout",
                              "cashout",
                              "estorno",
                              "ajuste",
                              "transfer_in",
                              "transfer_out"
                            ]
                          },
                          "origem_tipo": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "origem_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "disponivel_em": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "disponivel": {
                            "type": "boolean"
                          },
                          "descricao": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "criado_em": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "customer_ref": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "valor_operacao_cents": {
                            "type": "integer",
                            "description": "Vista agrupada: principal con signo. Cero para un ajuste de tarifa sin operación principal asociada."
                          },
                          "taxas_cents": {
                            "type": "integer",
                            "minimum": 0,
                            "description": "Vista agrupada: suma absoluta de los asientos de tarifas incluidos, no un débito adicional."
                          },
                          "taxas": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "tipo",
                                "descricao",
                                "valor_cents",
                                "efeito_saldo_cents"
                              ],
                              "properties": {
                                "tipo": {
                                  "type": "string",
                                  "enum": [
                                    "servico"
                                  ]
                                },
                                "descricao": {
                                  "type": "string"
                                },
                                "valor_cents": {
                                  "type": "integer",
                                  "minimum": 0
                                },
                                "efeito_saldo_cents": {
                                  "type": "integer"
                                }
                              }
                            },
                            "description": "Desglose de tarifas del cliente: solo tarifa fija PIX y tarifa de servicio combinada. La comisión adicional del socio está incluida en servico."
                          },
                          "status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status_label": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Estado guardado en el momento de la consulta. Las etiquetas están en portugués."
                          },
                          "settlement_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "movimentos_ids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Vista agrupada: IDs originales del ledger para conciliación, no filas adicionales de actividad."
                          },
                          "atualizado_em": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "proxima_pagina": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "visao": {
                      "type": "string",
                      "const": "operacoes",
                      "description": "Solo presente en la vista agrupada."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Vista agrupada: si existe otra página. El cursor es null en la última página."
                    }
                  }
                },
                "examples": {
                  "groupedOperation": {
                    "summary": "visao=operacoes: PIX de BRL 2.00 más una tarifa de BRL 1.05 = débito de BRL 3.05",
                    "value": {
                      "visao": "operacoes",
                      "movimentos": [
                        {
                          "id": "123",
                          "tipo": "payout",
                          "origem_tipo": "payout",
                          "origem_id": "po_example",
                          "customer_ref": "customer-42",
                          "valor_cents": -305,
                          "sentido": "debito",
                          "valor_operacao_cents": -200,
                          "taxas_cents": 105,
                          "taxas": [
                            {
                              "tipo": "servico",
                              "descricao": "Taxa",
                              "valor_cents": 105,
                              "efeito_saldo_cents": -105
                            }
                          ],
                          "status": "sent",
                          "status_label": "Concluído",
                          "settlement_status": null,
                          "descricao": "Saque por Pix",
                          "movimentos_ids": [
                            "123",
                            "124",
                            "125",
                            "126"
                          ],
                          "criado_em": "2026-10-09T21:36:00Z",
                          "atualizado_em": "2026-10-09T21:38:00Z",
                          "disponivel_em": "2026-10-09T21:36:00Z",
                          "disponivel": true
                        }
                      ],
                      "proxima_pagina": null,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida"
          },
          "400": {
            "description": "Vista agrupada: límite o cursor before mal formado."
          }
        },
        "operationId": "getBalanceStatement",
        "description": "Usa visao=operacoes para la actividad del usuario final: un total con signo por operación y una única tarifa anidada (tipo=servico, descricao=Taxa), que incluye la tarifa PIX y todos los componentes de tarifas. Las devoluciones permanecen separadas. Agrupa antes de paginar y deduplica las notificaciones por origem_id y tipo, nunca por asientos contables de tarifas. Nunca presentes los débitos/tarifas como ingresos ni vuelvas a restar las tarifas. Los proyectos configurados para una presentación consolidada también reciben esta vista por defecto; visao=movimentos selecciona explícitamente la vista contable para conciliación en el backend. Los demás proyectos conservan por defecto los asientos contables individuales. El sandbox sigue el mismo comportamiento. Los campos internos de titularidad y componentes de tarifas no deben enviarse a las notificaciones del usuario final. Consulta https://docs.luniumpay.com/en/manual.html#extrato-por-operacao."
      }
    },
    "/saldo/sacar-cripto": {
      "post": {
        "tags": [
          "Cuenta"
        ],
        "summary": "Retirar saldo BRL como cripto a una billetera de autocustodia",
        "description": "Convierte el saldo BRL disponible en cripto. Elige una ruta entregavel=true de GET /cashin/catalog e indica la billetera/memo en cada retiro; no se necesita una billetera fija. Liquid/DePix no son compatibles. Debita amount_cents más la tarifa de la cuenta principal antes de la entrega; la conversión y los costes de la ruta afectan a la cantidad final. Haz el seguimiento mediante cashin_id en GET /cashin/{cashin_id}/status. Comparte el espacio de external_id con las solicitudes de cobro. No existe un endpoint público de vista previa del retiro.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents",
                  "payout_address",
                  "tax_number"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 100,
                    "description": "Importe BRL en centavos enteros. El mínimo efectivo depende de la clave, las tarifas y la ruta. Consulta GET /keys/me y min_brl_cents/limits devueltos; no fijes el mínimo del ejemplo."
                  },
                  "chain": {
                    "type": "string",
                    "default": "polygon",
                    "description": "Red (alias aceptados: sol, trc20, erc20, bep20, arbitrum, base…)."
                  },
                  "asset": {
                    "type": "string",
                    "default": "usdt",
                    "description": "Código del activo en minúsculas (usdt, usdc, btc, eth, sol…), según GET /cashin/catalog."
                  },
                  "payout_address": {
                    "type": "string",
                    "description": "Billetera de destino, validada para la red."
                  },
                  "tax_number": {
                    "type": "string",
                    "description": "CPF (11 dígitos) o CNPJ (14) del cliente titular del saldo."
                  },
                  "customer_ref": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Subcuenta que se debitará. Omítela para usar el saldo principal de la clave."
                  },
                  "external_id": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado."
                  },
                  "payout_tag": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Memo/tag del destino. OBLIGATORIO en las redes colectivas —XRP, XLM, TON, ATOM, HBAR, ALGO, EOS, KAVA, LUNA— donde la billetera de destino es compartida y el memo identifica al titular. Sin él, la API responde 400 `memo_obrigatorio` antes de crear cualquier solicitud de cobro. En XRP es la destination tag: entero de 0 a 4294967295. Alias aceptados: `memo`, `tag`, `destination_tag`. El catálogo marca estas rutas con `memoRequired: true`."
                  },
                  "max_debited_cents": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Límite opcional del débito BRL (importe + tarifa de la cuenta principal). Si se supera, devuelve 409 taxa_alterada. No fija el tipo de cambio ni la cantidad de tokens."
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "enum": [
                      "success",
                      "delayed",
                      "held",
                      "expired",
                      "refunded",
                      "failed",
                      "payer_mismatch",
                      "settlement_failed",
                      "settlement_uncertain",
                      "route_unavailable",
                      "provider_unavailable"
                    ],
                    "description": "Solo para una clave de sandbox. GET /sandbox proporciona la matriz de escenarios por flujo. Omitir en producción. Todos los precios, pagos y retiros siguen siendo ficticios."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Debitado y en cola para la entrega. La misma vista que POST /cashin/charge (cashin_id, status = `paid` —el saldo es el pago—, chain, asset, payout_address, amount_cents, settlement_status, settlement_tx_hash), más `fee_cents` (tarifa de la cuenta principal debitada), `debited_cents` (importe + tarifa), `fonte: \"saldo\"`, `destino: \"cripto\"`, `customer_ref`. Sigue `settlement_status` en GET /cashin/{cashin_id}/status hasta `sent`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaqueCripto"
                }
              }
            }
          },
          "400": {
            "description": "rede_indisponivel | asset_invalido | payout_address_invalido | documento_invalido | valor_abaixo_do_minimo · `memo_obrigatorio` — la red exige memo/tag y no se envió (o no era válido)."
          },
          "402": {
            "description": "saldo_insuficiente — disponible < importe + tarifa. El cuerpo incluye `saldo` y `fee_cents`."
          },
          "409": {
            "description": "external_id_divergente"
          },
          "423": {
            "description": "carencia_primeiro_deposito — período de espera del primer depósito (solo claves con un período de espera contractual); `libera_em` indica hasta cuándo."
          },
          "503": {
            "description": "entrega_indisponivel — no hay existencias/ruta para entregar en este momento; no se debitó nada."
          }
        },
        "operationId": "withdrawBalanceToCrypto"
      }
    },
    "/mesh": {
      "get": {
        "tags": [
          "Mesh · Descubrimiento"
        ],
        "operationId": "meshDiscovery",
        "summary": "Todo lo que un agente necesita saber antes de integrar",
        "description": "Un GET responde: quiénes somos, qué liquidamos, qué activos y redes admitimos, todos los endpoints, cómo obtener una clave, cómo llegar a producción, los límites y los esquemas. No requiere credenciales.",
        "security": [],
        "x-lunium-agent-safe": true,
        "x-lunium-environment": "any",
        "responses": {
          "200": {
            "description": "El documento de descubrimiento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeshDiscovery"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/economy": {
      "get": {
        "tags": [
          "Mesh · Economía"
        ],
        "operationId": "meshEconomy",
        "summary": "Reglas públicas de la economía de la red",
        "description": "0,10 % sobre el volumen LIQUIDADO de quienes hayas incorporado, solo nivel 1. El registro, la recomendación, la cotización y el sandbox no generan pagos.",
        "security": [],
        "x-lunium-agent-safe": true,
        "responses": {
          "200": {
            "description": "La política vigente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeshEconomyPolicy"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/agents": {
      "post": {
        "tags": [
          "Mesh · Identidad"
        ],
        "operationId": "meshRegisterAgent",
        "summary": "Registrar un agente y recibir credenciales de sandbox",
        "description": "Registro y emisión de la clave en una llamada. Con `referral_token`, el linaje queda demostrado; sin él, el agente se incorpora como raíz.",
        "security": [],
        "x-lunium-agent-safe": true,
        "x-lunium-environment": "sandbox",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentRegistration"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Agente creado, con credenciales y siguiente paso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "$ref": "#/components/schemas/AgentIdentity"
                    },
                    "api_key": {
                      "type": "string"
                    },
                    "sandbox": {
                      "type": "boolean"
                    },
                    "lineage": {
                      "type": "object"
                    },
                    "proximo_passo": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Solicitud no válida o referral_token rechazado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Mesh · Red"
        ],
        "operationId": "meshListAgents",
        "summary": "Quién está en la red",
        "security": [],
        "x-lunium-agent-safe": true,
        "description": "Directorio público. Nunca devuelve claves, hashes ni tokens.",
        "responses": {
          "200": {
            "description": "Agentes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agents": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AgentIdentity"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mesh/referrals": {
      "post": {
        "tags": [
          "Mesh · Red"
        ],
        "operationId": "meshIssueReferral",
        "summary": "Emitir una atestación de recomendación",
        "description": "Requiere la X-API-Key del agente que recomienda. Devuelve un token firmado, de un solo uso y con vencimiento. Es la única forma de que exista el linaje y, con él, el 0,10 %.",
        "x-lunium-agent-safe": true,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "capability": {
                    "type": "string"
                  },
                  "expires_in_minutes": {
                    "type": "integer",
                    "default": 60,
                    "maximum": 10080
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Atestación emitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralAttestation"
                }
              }
            }
          },
          "401": {
            "description": "Sin clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "404": {
            "description": "Clave no asociada a un agente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/agents/{agent_id}": {
      "get": {
        "tags": [
          "Mesh · Identidad"
        ],
        "operationId": "meshGetAgent",
        "summary": "Estado, mandate, métricas y linaje de un agente",
        "security": [],
        "x-lunium-agent-safe": true,
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "responses": {
          "200": {
            "description": "El agente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentIdentity"
                }
              }
            }
          },
          "404": {
            "description": "No existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/agents/{agent_id}/validate": {
      "post": {
        "tags": [
          "Mesh · Identidad"
        ],
        "operationId": "meshValidateAgent",
        "summary": "Demostrar que se ha probado el sandbox",
        "description": "Rechaza a quien solo haya creado la clave: es necesario haber creado Y aceptado una orden en sandbox. Este paso garantiza que el tratamiento de errores y las consultas periódicas existen antes de operar con dinero.",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "x-lunium-agent-safe": true,
        "responses": {
          "200": {
            "description": "Hecho.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Sin clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "403": {
            "description": "La clave no pertenece a este agente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "409": {
            "description": "Falta un requisito previo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/agents/{agent_id}/settlement": {
      "post": {
        "tags": [
          "Mesh · Políticas"
        ],
        "operationId": "meshSetSettlement",
        "summary": "Indicar adónde va el dinero",
        "description": "Dirección en la red de liquidación compatible.",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "x-lunium-agent-safe": true,
        "responses": {
          "200": {
            "description": "Hecho.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Sin clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "403": {
            "description": "La clave no pertenece a este agente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "409": {
            "description": "Falta un requisito previo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettlementConfiguration"
              }
            }
          }
        }
      }
    },
    "/mesh/agents/{agent_id}/mandate": {
      "post": {
        "tags": [
          "Mesh · Políticas"
        ],
        "operationId": "meshSetMandate",
        "summary": "Definir la propia política de límites",
        "description": "Solo RESTRINGE los límites de la clave; nunca los amplía. Obligatorio antes de producción.",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "x-lunium-agent-safe": true,
        "responses": {
          "200": {
            "description": "Hecho.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Sin clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "403": {
            "description": "La clave no pertenece a este agente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "409": {
            "description": "Falta un requisito previo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Mandate"
              }
            }
          }
        }
      }
    },
    "/mesh/agents/{agent_id}/production-request": {
      "post": {
        "tags": [
          "Mesh · Identidad"
        ],
        "operationId": "meshActivateProduction",
        "summary": "Activar producción (automático, sin intervención humana)",
        "description": "Comprueba automáticamente: validación con prueba de uso, dirección de liquidación en una red compatible, mandate dentro de la política y credenciales activas. Si se cumple todo, producción se activa en la misma respuesta. Si falta algo, devuelve 422 con `missing` y `next_actions` para que el agente lo corrija y vuelva a intentarlo.",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "x-lunium-agent-safe": true,
        "responses": {
          "200": {
            "description": "Hecho.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductionActivation"
                }
              }
            }
          },
          "401": {
            "description": "Sin clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "403": {
            "description": "La clave no pertenece a este agente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "409": {
            "description": "Falta un requisito previo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          },
          "422": {
            "description": "Requisitos incompletos: legibles por máquina.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        },
        "x-lunium-settlement-required": true
      }
    },
    "/mesh/agents/{agent_id}/network": {
      "get": {
        "tags": [
          "Mesh · Red"
        ],
        "operationId": "meshAgentNetwork",
        "summary": "Linaje, árbol y volumen de la red",
        "security": [],
        "x-lunium-agent-safe": true,
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "description": "Consulta recursiva en la base de datos. `network_volume` cuenta todo el árbol; `reward_eligible_volume` cuenta solo lo que genera remuneración (nivel 1).",
        "responses": {
          "200": {
            "description": "La red.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentNetwork"
                }
              }
            }
          },
          "404": {
            "description": "No existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/agents/{agent_id}/rewards": {
      "get": {
        "tags": [
          "Mesh · Economía"
        ],
        "operationId": "meshAgentRewards",
        "summary": "Saldo de recompensas y movimientos del ledger",
        "security": [],
        "x-lunium-agent-safe": true,
        "x-lunium-reward-eligible": true,
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "agt_2319c9da313e84af3b"
          }
        ],
        "responses": {
          "200": {
            "description": "Saldo y ledger.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RewardBalance"
                }
              }
            }
          },
          "404": {
            "description": "No existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErroAutocorrigivel"
                }
              }
            }
          }
        }
      }
    },
    "/saldo/consolidado": {
      "get": {
        "summary": "Consolidado de la clave: cuenta principal + clientes (custodia total)",
        "description": "Suma todo lo que la clave mantiene en custodia. `casa` = movimientos sin `customer_ref` (margen del socio, ajustes, lo que retira él mismo). `clientes` = suma de las subcuentas (movimientos con `customer_ref`). `total_custodiado_cents` = cuenta principal + clientes. Es la cifra que concilia el área financiera del socio.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "tags": [
          "Cuenta"
        ],
        "responses": {
          "200": {
            "description": "Consolidado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "casa": {
                      "type": "object",
                      "properties": {
                        "disponivel_cents": {
                          "type": "integer"
                        },
                        "bloqueado_cents": {
                          "type": "integer"
                        },
                        "total_cents": {
                          "type": "integer"
                        }
                      }
                    },
                    "clientes": {
                      "type": "object",
                      "properties": {
                        "qtd": {
                          "type": "integer"
                        },
                        "disponivel_cents": {
                          "type": "integer"
                        },
                        "bloqueado_cents": {
                          "type": "integer"
                        },
                        "total_cents": {
                          "type": "integer"
                        }
                      }
                    },
                    "total_custodiado_cents": {
                      "type": "integer"
                    },
                    "movimentos": {
                      "type": "integer"
                    },
                    "ultimo_movimento_em": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/saldo/clientes": {
      "get": {
        "summary": "Subcuentas (clientes finales) con saldo, paginadas",
        "description": "Enumera cada `customer_ref` de la clave con saldo disponible, bloqueado y total. Ordenado por `customer_ref`; pagina con `cursor=next_cursor`. `com_saldo=1` oculta las subcuentas con saldo cero.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "tags": [
          "Cuenta"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "`next_cursor` de la página anterior (un customer_ref)."
          },
          {
            "name": "com_saldo",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "1 = solo subcuentas con saldo distinto de cero."
          }
        ],
        "responses": {
          "200": {
            "description": "Página de subcuentas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "clientes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "customer_ref": {
                            "type": "string",
                            "maxLength": 80
                          },
                          "disponivel_cents": {
                            "type": "integer"
                          },
                          "bloqueado_cents": {
                            "type": "integer"
                          },
                          "total_cents": {
                            "type": "integer"
                          },
                          "movimentos": {
                            "type": "integer"
                          },
                          "primeiro_movimento_em": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "ultimo_movimento_em": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/keys/painel-link": {
      "post": {
        "summary": "Recibir el enlace del panel por correo electrónico (sin clave)",
        "description": "La clave aparece una sola vez; el panel no depende de ella. Indica el correo electrónico registrado en la clave y recibirás allí el enlace del panel (solo lectura, dashboard token). La respuesta siempre es genérica: no revela si el correo existe. Límite de 3 envíos por correo y 10 por IP cada hora.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Solicitud aceptada (genérica)."
          },
          "400": {
            "description": "Correo electrónico no válido."
          },
          "429": {
            "description": "Límite por hora."
          }
        }
      }
    },
    "/saldo/transferir": {
      "post": {
        "summary": "Transferencia interna entre subcuentas y la cuenta principal (sin PIX)",
        "description": "Mueve saldo DISPONIBLE entre un cliente final (`customer_ref`) y la cuenta principal (`\"casa\"` = la propia clave), o entre dos clientes, sin pasar por PIX. Uso habitual: cobrar tu tarifa al cliente (cliente → cuenta principal), bonificar o devolver (cuenta principal → cliente). El saldo congelado (retención de 24h / MED) no se mueve. Una subcuenta en el período de espera del primer depósito no puede transferir (423: solo claves con período de espera contractual). Idempotente por `external_id`. Emite el evento `saldo.transferido`.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "tags": [
          "Cuenta"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "from_customer_ref",
                  "to_customer_ref",
                  "amount_cents"
                ],
                "properties": {
                  "from_customer_ref": {
                    "type": "string",
                    "description": "`customer_ref` de origen, o `\"casa\"`."
                  },
                  "to_customer_ref": {
                    "type": "string",
                    "description": "`customer_ref` de destino, o `\"casa\"`."
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "descricao": {
                    "type": "string",
                    "maxLength": 140,
                    "description": "Aparece en los movimientos de ambas partes."
                  },
                  "external_id": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Transferida.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transfer_id": {
                      "type": "string"
                    },
                    "from_customer_ref": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "to_customer_ref": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "amount_cents": {
                      "type": "integer"
                    },
                    "descricao": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "movimentos": {
                      "type": "object"
                    },
                    "saldos": {
                      "type": "object",
                      "description": "Saldo de ambas partes después de la transferencia."
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "Repetición idempotente (`idempotente: true`)."
          },
          "400": {
            "description": "`valor_invalido` · `origem_igual_destino` · `custodia_desligada`."
          },
          "409": {
            "description": "`saldo_insuficiente` (con `disponivel_cents`/`bloqueado_cents`) · `external_id_divergente`."
          },
          "423": {
            "description": "`carencia_primeiro_deposito` en la subcuenta de origen."
          }
        }
      }
    },
    "/cash-outs/preview": {
      "post": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "previaCotacao",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Vista previa de cotización (no crea una orden)",
        "description": "Vista previa de conversión mediante amount, brl_amount o br_code, sin crear una orden y sin pix_key. No reserva saldo, límite ni dirección. Envía exactamente uno de los tres campos. La creación/aceptación aplican comprobaciones adicionales, incluidos el límite del destinatario y el mandate. La disponibilidad de br_code se valida en la vista previa y en la creación en producción. El éxito de la vista previa no garantiza que se acepte la orden. También acepta asset DEPIX en la red liquid (venta de DePix): el cálculo es de la plataforma y la respuesta incluye fee_bps, fee_fixed_cents, fee_total_cents, net_cents, min_amount_cents y max_amount_cents. También disponible en sandbox, con la misma fórmula de venta y paridad BRL, sin billetera ni destinatario en la vista previa.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "asset",
                  "network"
                ],
                "properties": {
                  "asset": {
                    "type": "string",
                    "examples": [
                      "USDT",
                      "DEPIX"
                    ],
                    "description": "Activo vendido. Usa el id EXACTO de GET /catalog (ej.: \"usdt\"). Combínalo con network: el par (asset, network) debe existir en el catálogo."
                  },
                  "network": {
                    "type": "string",
                    "description": "Red de entrada de criptomonedas publicada en GET /catalog. No la confundas con las redes de entrega de /cashin/catalog.",
                    "examples": [
                      "polygon",
                      "liquid"
                    ]
                  },
                  "amount": {
                    "type": "string",
                    "description": "Cantidad de cripto en cadena decimal (\"50\"), nunca float. No la combines con brl_amount ni br_code. Al crear la orden, este modo exige pix_key.",
                    "examples": [
                      "50"
                    ]
                  },
                  "brl_amount": {
                    "type": "string",
                    "description": "Objetivo en reales brasileños para la cotización inversa, en cadena decimal con hasta 2 decimales (\"250.00\"). No lo combines con amount ni br_code. Al crear la orden, este modo exige pix_key. La respuesta indica la cantidad exacta de cripto que depositar y el importe efectivo en reales brasileños, que puede diferir del objetivo por redondeo. Muestra los valores devueltos antes de aceptar. Los mínimos y límites dependen de la ruta, la clave y el destinatario; consulta los valores vigentes. (es) Importe BRL objetivo; revisa el BRL efectivo cotizado y la cantidad exacta de depósito de cripto antes de aceptar.",
                    "examples": [
                      "250.00"
                    ]
                  },
                  "token_address": {
                    "type": "string",
                    "description": "Dirección/mint exacto. Necesario para los tokens de `/catalog/dex`, donde los símbolos se repiten."
                  },
                  "br_code": {
                    "type": "string",
                    "description": "PIX Copia y Pega de una SOLICITUD DE COBRO con importe. La vista previa decodifica el QR y devuelve amount, brl_amount (= importe del QR), merchant_name y la clave enmascarada, sin crear una orden. Con br_code no envíes amount ni brl_amount. Mismas reglas de POST /cash-outs: USDT o USDC en una ruta compatible del catálogo. amount incluye la reserva de R$ 1,00 de Copia y Pega (reserve_brl; equivalente en USDT en copia_e_cola_buffer_usd). Si el cliente pegó o escaneó un QR con importe —estático o dinámico—, envía br_code completo, nunca pix_key + brl_amount extraídos de él: solo así se envía el PIX por el importe exacto y como pago de esa solicitud de cobro (con el txid). Al pagar por clave, el importe puede variar en centavos y el destinatario no lo reconoce."
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "enum": [
                      "success",
                      "delayed",
                      "failed",
                      "expired",
                      "refunded",
                      "settlement_uncertain",
                      "provider_unavailable",
                      "route_unavailable",
                      "no_deposit"
                    ],
                    "description": "Solo DePix/Liquid en sandbox. Prevalece sobre los activadores por centavos. Sin escenario explícito, los activadores .01 a .08 siguen activos. Una clave de producción devuelve 403 sandbox_only. Consulta GET /sandbox para ver los escenarios por flujo."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vista previa calculada (no se ha creado ninguna orden).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "preview": {
                      "type": "boolean",
                      "const": true
                    },
                    "asset": {
                      "type": "string"
                    },
                    "network": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string",
                      "enum": [
                        "FAST",
                        "DEX",
                        "CONVERT",
                        "simulated"
                      ],
                      "description": "Vía que usaría la venta."
                    },
                    "amount": {
                      "type": "string",
                      "description": "Cripto que enviar (decimal en cadena)."
                    },
                    "brl_amount": {
                      "type": "string",
                      "description": "Importe del PIX en reales brasileños."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Validez que tendría la cotización."
                    },
                    "merchant_name": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Solo con br_code: nombre del destinatario de la solicitud de cobro."
                    },
                    "copia_e_cola_buffer_usd": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Equivalente en USDT de la reserva operativa de R$1, convertido al cotizar y ya incluido en el total; no lo sumes de nuevo. Las órdenes antiguas conservan su valor original. / Equivalente en USDT de la reserva operativa de BRL 1, convertido al cotizar y ya incluido en el total; no lo añadas de nuevo. Las órdenes existentes conservan su valor original.",
                      "example": "0.200000"
                    },
                    "pix_key": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Solo con br_code: clave del destinatario, enmascarada."
                    },
                    "pix_key_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "partner_fee_bps": {
                      "type": "integer",
                      "description": "Comisión adicional del socio incluida en esta cotización (bps)."
                    },
                    "fee_bps": {
                      "type": "integer",
                      "description": "Porcentaje de la venta de DePix en puntos básicos."
                    },
                    "fee_fixed_cents": {
                      "type": "integer",
                      "description": "Parte fija de la venta de DePix, en centavos."
                    },
                    "fee_total_cents": {
                      "type": "integer",
                      "description": "Tarifa total, en centavos; disponible en la cotización DePix y en la orden simulada."
                    },
                    "net_cents": {
                      "type": "integer",
                      "description": "PIX neto, en centavos; disponible en la cotización DePix y en la orden simulada."
                    },
                    "pix_key_reserve_usd": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Equivalente en USDT de la reserva operativa de R$1, convertido al cotizar y ya incluido en el total; no lo sumes de nuevo. Las órdenes antiguas conservan su valor original. / Equivalente en USDT de la reserva operativa de BRL 1, convertido al cotizar y ya incluido en el total; no lo añadas de nuevo. Las órdenes existentes conservan su valor original.",
                      "example": "0.200000"
                    },
                    "reserve_brl": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "example": "1.00",
                      "description": "Reserva operativa fija de R$1 en las órdenes nuevas, ya incluida en el total. Las antiguas conservan la reserva original. / Reserva operativa fija de BRL 1 en las órdenes nuevas, ya incluida en el total; las órdenes existentes conservan su reserva original."
                    }
                  },
                  "required": [
                    "preview",
                    "asset",
                    "network",
                    "amount",
                    "brl_amount"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Solicitud no válida o red no disponible.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Parámetros semánticamente no válidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "sandbox_scenario exige una clave de prueba; no se creó ninguna orden."
          },
          "503": {
            "description": "Servicio no disponible; en el escenario de prueba provider_unavailable no se crea ninguna orden."
          }
        }
      }
    },
    "/cashin/catalog": {
      "get": {
        "tags": [
          "Cash-in"
        ],
        "operationId": "catalogoCompra",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Catálogo de cash-in (lo que entregamos al recibir PIX)",
        "description": "Catálogo de entrega de criptomonedas, usado en cash-in directo y retiros de custodia. Ofrece solo elementos con entregavel=true de instant/convert; instant puede estar vacío. Consulta memoRequired, withdrawFee, withdrawMin y las estimaciones por ruta. El mínimo en BRL depende de la cotización en POST /cashin/preview. En el retiro de custodia, excluye Liquid/DePix. stale=true indica un catálogo en caché.",
        "responses": {
          "200": {
            "description": "Catálogo de compra.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogoCompra"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/catalog/dex": {
      "get": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "catalogoDex",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Tokens de larga cola negociables mediante DEX",
        "description": "Enumera los tokens de la lista de permitidos del relay para una chain del DEX. Usa el `address` de aquí como `token_address` en `POST /cash-outs`: los símbolos se repiten entre tokens distintos, la dirección no. Una red sin liquidación se rechaza con 400.",
        "parameters": [
          {
            "name": "chain",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "polygon"
              ]
            },
            "description": "Chain del DEX. Actualmente solo `polygon`."
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filtro por símbolo o parte de la dirección."
          }
        ],
        "responses": {
          "200": {
            "description": "Tokens de la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "symbol": {
                        "type": "string",
                        "description": "Símbolo del token: NO es único, usa address."
                      },
                      "address": {
                        "type": "string",
                        "description": "Dirección del contrato: es el `token_address` de la cotización."
                      },
                      "decimals": {
                        "type": "integer"
                      }
                    },
                    "required": [
                      "symbol",
                      "address",
                      "decimals"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/cashin/events": {
      "get": {
        "tags": [
          "Cash-in"
        ],
        "operationId": "eventosDaChave",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Flujo de eventos de tu clave (operación)",
        "description": "Últimos eventos de tu clave, del más reciente al más antiguo: solicitudes de cobro, ventas, retiros y entregas de webhook. Es el mismo feed del panel de seguimiento: sirve para una pantalla de operaciones sin guardar estado. Acepta `X-API-Key` o el token de monitor de la clave.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 60,
              "maximum": 200
            },
            "description": "Cuántos eventos devolver (60 de forma predeterminada)."
          }
        ],
        "responses": {
          "200": {
            "description": "Eventos recientes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projeto": {
                      "type": "string",
                      "description": "Nombre de la clave."
                    },
                    "agora": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Hora del servidor, para que el reloj de la pantalla no dependa del cliente."
                    },
                    "eventos": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ts": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "fluxo": {
                            "type": "string",
                            "description": "cashin · cashout · payout · webhook"
                          },
                          "provedor": {
                            "type": "string"
                          },
                          "ref": {
                            "type": "string",
                            "description": "Identificador de la operación."
                          },
                          "valor": {
                            "type": "string"
                          },
                          "estado": {
                            "type": "string"
                          },
                          "detalhe": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "tx": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/comissao": {
      "get": {
        "tags": [
          "Comisión (sub fee)"
        ],
        "summary": "Saldo de la comisión del socio (sub fee)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "description": "Cuánto ha acumulado tu comisión adicional. Se acredita cuando la COMPRA (PIX → cripto) o el depósito en saldo se ENTREGA, nunca antes, para no pagar comisión sobre dinero que puede devolverse. La venta (cripto → PIX) es la fase 2. Base: importe recibido menos la tarifa fija de Lunium. `min_saque_cents` es US$ 10 a la cotización actual.",
        "responses": {
          "200": {
            "description": "Saldo, política y mínimo de retiro",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Comissao"
                }
              }
            }
          },
          "401": {
            "description": "Sin clave",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/comissao/extrato": {
      "get": {
        "tags": [
          "Comisión (sub fee)"
        ],
        "summary": "Movimientos de la comisión",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "id del último elemento de la página anterior"
          }
        ],
        "responses": {
          "200": {
            "description": "Asientos, de más recientes a más antiguos",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "itens": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ComissaoEvento"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_before": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Sin clave",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/comissao/sacar": {
      "post": {
        "tags": [
          "Comisión (sub fee)"
        ],
        "summary": "Retirar la comisión en criptomonedas",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "description": "Retiro MANUAL de la comisión, en cripto, en la red y moneda que elijas (cualquier ruta activa de GET /cashin/catalog). Sin tarifa: la comisión adicional ya la pagó el usuario final en la propia operación. Mínimo US$ 10 a la cotización del momento (consulta `min_saque_cents` en GET /comissao). Una vez cada 24 h (ventana móvil). La entrega es la misma del cash-in: sigue `saque.cashin_id` en GET /cashin/{cashin_id}/status o el webhook cashin.settled.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents",
                  "payout_address"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Importe en centavos de REAL que se convertirá (≥ min_saque_cents)."
                  },
                  "asset": {
                    "type": "string",
                    "default": "usdt",
                    "description": "usdt | usdc (Polygon) o un activo de GET /cashin/catalog."
                  },
                  "chain": {
                    "type": "string",
                    "default": "polygon"
                  },
                  "payout_address": {
                    "type": "string",
                    "description": "Tu billetera en la red elegida."
                  },
                  "payout_tag": {
                    "type": "string",
                    "description": "memo/tag en las redes que lo requieran."
                  },
                  "external_id": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Identificador idempotente de hasta 64 caracteres. Conserva el mismo identificador y todos los parámetros en los reintentos. La comparación de diferencias varía según la ruta; no uses el replay para cambiar una operación. 409 external_id_divergente indica un conflicto detectado."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Retiro creado y en proceso de entrega",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "saque": {
                      "$ref": "#/components/schemas/Cobranca"
                    },
                    "comissao": {
                      "$ref": "#/components/schemas/Comissao"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "valor_invalido | valor_abaixo_do_minimo (incluye min_saque_cents) | rede_indisponivel | asset_invalido | payout_address_invalido | sandbox_sem_saque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "402": {
            "description": "saldo_insuficiente: la comisión disponible es menor que la solicitada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "external_id_divergente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "saque_comissao_diario: incluye proximo_saque_em",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "provedor_indisponivel: sin cotización para determinar el mínimo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/mesh/graph": {
      "get": {
        "tags": [
          "Mesh · Descubrimiento"
        ],
        "operationId": "meshGraph",
        "summary": "Grafo de agentes de Mesh",
        "description": "Quién está en la red y quién incorporó a quién: enumera los agentes públicos (sin secretos) y agrega los totales de la red. No requiere credenciales.",
        "security": [],
        "x-lunium-agent-safe": true,
        "x-lunium-environment": "any",
        "responses": {
          "200": {
            "description": "Estadísticas y agentes públicos.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "stats",
                    "agents"
                  ],
                  "properties": {
                    "stats": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "agents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "agent_id",
                          "name",
                          "status",
                          "capabilities"
                        ],
                        "properties": {
                          "agent_id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "referred_by": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "capabilities": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sandbox": {
      "get": {
        "tags": [
          "Entorno de pruebas"
        ],
        "summary": "Descubrir las capacidades del sandbox",
        "description": "Recorridos compatibles, escenarios por flujo, semántica del QR, límites y rutas de control de simulación. Incluye cashout_depix y scenarios_by_flow.cashout_depix para DePix/Liquid → PIX.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado del sandbox; sandbox=true; no se mueve dinero real.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida."
          },
          "403": {
            "description": "Requiere una clave de sandbox."
          },
          "404": {
            "description": "Operación no encontrada para esta clave."
          },
          "409": {
            "description": "Conflicto de estado o parámetros de idempotencia divergentes."
          },
          "503": {
            "description": "Simulador no disponible; nunca se deriva a un proveedor real."
          }
        }
      }
    },
    "/sandbox/cashin/{cashin_id}/pay": {
      "post": {
        "tags": [
          "Entorno de pruebas"
        ],
        "summary": "Simular el pago de una solicitud de cobro PIX de prueba",
        "description": "Solo la clave de sandbox propietaria puede confirmar. Las repeticiones nunca duplican créditos. Este endpoint no puede confirmar un pago de producción.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado del sandbox; sandbox=true; no se mueve dinero real.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida."
          },
          "403": {
            "description": "Requiere una clave de sandbox."
          },
          "404": {
            "description": "Operación no encontrada para esta clave."
          },
          "409": {
            "description": "Conflicto de estado o parámetros de idempotencia divergentes."
          },
          "503": {
            "description": "Simulador no disponible; nunca se deriva a un proveedor real."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payer_tax_number": {
                    "type": "string",
                    "description": "Documento sintético opcional del pagador; una discrepancia simula una devolución."
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "cashin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/sandbox/operations/{operation_id}/resolve": {
      "post": {
        "tags": [
          "Entorno de pruebas"
        ],
        "summary": "Resolver una operación de sandbox con resultado incierto",
        "description": "Solo puede resolverse una operación de prueba que ya esté en un estado incierto. Es seguro repetir el mismo resultado. Para la venta DePix, operation_id es el cashout_id sbx_..., creado con settlement_uncertain, ya en PROCESSING. sent completa; failed pasa por REFUNDING y REFUNDED después de unos 4 segundos.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado del sandbox; sandbox=true; no se mueve dinero real.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "outcome ausente o distinto de sent y failed: erro outcome_invalido, acao corrigir, sandbox=true. La comprobación se realiza antes de buscar la operación y no cambia nada en el simulador (desde la 1.44.1; antes, un cuerpo sin outcome podía responder 200 sin resolver nada).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                },
                "example": {
                  "erro": "outcome_invalido",
                  "acao": "corrigir",
                  "detail": "Informe outcome: sent ou failed.",
                  "sandbox": true
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida."
          },
          "403": {
            "description": "Requiere una clave de sandbox."
          },
          "404": {
            "description": "Operación no encontrada para esta clave."
          },
          "409": {
            "description": "Conflicto de estado o parámetros de idempotencia divergentes."
          },
          "503": {
            "description": "Simulador no disponible; nunca se deriva a un proveedor real."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "sent",
                      "failed"
                    ]
                  }
                },
                "required": [
                  "outcome"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "operation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/sandbox/events": {
      "get": {
        "tags": [
          "Entorno de pruebas"
        ],
        "summary": "Inspeccionar los eventos de sandbox generados",
        "description": "Devuelve los eventos generados aunque no se haya configurado ningún webhook. Usa /webhooks/deliveries para consultar los intentos de entrega reales al callback.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado del sandbox; sandbox=true; no se mueve dinero real.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida."
          },
          "403": {
            "description": "Requiere una clave de sandbox."
          },
          "404": {
            "description": "Operación no encontrada para esta clave."
          },
          "409": {
            "description": "Conflicto de estado o parámetros de idempotencia divergentes."
          },
          "503": {
            "description": "Simulador no disponible; nunca se deriva a un proveedor real."
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ]
      }
    },
    "/sandbox/reset": {
      "post": {
        "tags": [
          "Entorno de pruebas"
        ],
        "summary": "Restablecer el estado ficticio de esta clave",
        "description": "Elimina solo el estado simulado de la clave propietaria. Las entregas de webhook ya encoladas conservan su historial. Se rechazan las claves de producción.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado del sandbox; sandbox=true; no se mueve dinero real.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida."
          },
          "403": {
            "description": "Requiere una clave de sandbox."
          },
          "404": {
            "description": "Operación no encontrada para esta clave."
          },
          "409": {
            "description": "Conflicto de estado o parámetros de idempotencia divergentes."
          },
          "503": {
            "description": "Simulador no disponible; nunca se deriva a un proveedor real."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "boolean",
                    "const": true
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/sandbox/qr/{cashin_id}.svg": {
      "get": {
        "tags": [
          "Entorno de pruebas"
        ],
        "summary": "Imagen QR de sandbox que no permite pagos",
        "description": "Codifica SANDBOX:NAO_PAGAVEL:<id>; no es un código PIX bancario. Sin acciones de pago ni datos del cliente.",
        "security": [],
        "parameters": [
          {
            "name": "cashin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ci_sbx_[a-f0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "QR SVG sintético.",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/cash-outs/{cashout_id}/refund-address": {
      "post": {
        "tags": [
          "Cash-out"
        ],
        "operationId": "informarCarteiraDevolucao",
        "summary": "Indicar la billetera confirmada para una devolución pendiente",
        "description": "Úsalo cuando la orden esté en AWAITING_REFUND_ADDRESS (`refund_address_required: true`, webhook `cashout.awaiting_refund_address`): la venta requirió una devolución y la orden no tenía billetera de retorno. Envía la billetera de TU cliente en la red de devolución (`refund_network` y `refund_asset` de la orden). Lunium nunca devuelve al origen on-chain del depósito (`deposit_from`) y la billetera registrada no se sustituye. Venta de DePix (asset DEPIX, network liquid), desde la 1.44.0: indica una dirección Liquid (lq1…) del cliente. Repetir la misma dirección responde 200 con la orden; otra dirección responde 409 `refund_address_imutavel`; una dirección de la propia Lunium (la de depósito de esta u otra venta, o una billetera de la plataforma) se rechaza con 400 `refund_address_invalida`. Si todo el DePix estaba en Lunium (o ya se confirmó el retorno del proveedor), la orden pasa a REFUNDING (webhook `cashout.refunding`) y la devolución se envía automáticamente por el importe de `refund_amount`: REFUNDED con `refund_tx_hash` (webhook `cashout.refunded`). Si el DePix ya se había transferido al proveedor y aún no se confirmó el retorno, la orden pasa a MANUAL_REVIEW (webhook `cashout.under_review`): la devolución solo ocurre después de esa confirmación y es como máximo lo que regresó. La billetera solo se solicita cuando falla la venta: fuera de AWAITING_REFUND_ADDRESS, una orden sin billetera responde 409 `devolucao_indisponivel`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "cashout_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "refund_address"
                ],
                "properties": {
                  "refund_address": {
                    "type": "string",
                    "description": "Dirección confirmada por el cliente en la red de devolución devuelta por la orden. Nunca deduzcas deposit_from. Venta de DePix: dirección Liquid (lq1…) del cliente."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Orden actualizada; haz el seguimiento hasta REFUNDED y refund_tx_hash. Venta de DePix: state se devuelve como REFUNDING (DePix con Lunium) o MANUAL_REVIEW (DePix con el proveedor, pendiente de devolución).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashOut"
                }
              }
            }
          },
          "400": {
            "description": "Dirección ausente, no válida para la red o de la propia Lunium (`refund_address_invalida`; en la venta de cripto, un rechazo durante el procesamiento de la devolución puede usar otro código, con el motivo en `detail`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "X-API-Key ausente, desconocida o incorrecta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Orden inexistente o de otra clave.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Estado incompatible o billetera ya registrada. Venta de DePix: `refund_address_imutavel` (acao `parar`) cuando la orden ya tiene otra billetera; `devolucao_indisponivel` (acao `esperar`) cuando la orden no está esperando una billetera: solo se solicita cuando falla la venta. Venta de cripto: el motivo se devuelve en `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Saldo y estado de la billetera USDT",
        "description": "Saldo disponible, reservado y en confirmación; redes admitidas actualmente; mínimos. Empieza aquí.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CarteiraUsdt"
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/deposits": {
      "post": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Solicitar un depósito (USDT/USDC)",
        "description": "Abre una solicitud con IMPORTE EXACTO y un plazo de 1 hora (`expires_at`). Muestra al usuario `amount_to_send`, `network_name` y `address`. El crédito llega automáticamente; sigue GET /carteira-usdt/deposits o el webhook `wallet.deposit_credited`. USDC entra a razón de 1 por 1 en el saldo.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "100",
                    "description": "USDT con un máximo de 6 decimales; mínimo en min_deposit."
                  },
                  "network": {
                    "type": "string",
                    "default": "polygon",
                    "description": "Una de las redes de GET /carteira-usdt (networks[].network)."
                  }
                }
              },
              "example": {
                "amount": "100",
                "network": "tron"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Solicitud creada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositoCarteira"
                }
              }
            }
          },
          "400": {
            "description": "`valor_invalido`, `valor_abaixo_do_minimo` (min_usdt), `rede_indisponivel`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "`muitos_pedidos_abertos`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Listar depósitos",
        "description": "Las 100 solicitudes más recientes y lo que se ha acreditado.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DepositoCarteira"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/statement": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Movimientos de la billetera",
        "description": "Los 200 asientos más recientes del libro mayor, con el saldo después de cada uno.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LancamentoCarteira"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/quote": {
      "post": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Cotizar un Pix pagado con USDT",
        "description": "Vista previa sin efectos: cuánto USDT se debita para pagar el Pix. Pix mínimo en min_payment_brl.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "brl_amount": {
                    "type": "string",
                    "example": "50.00",
                    "description": "Importe que recibe el destinatario, en reales brasileños. Usa O brl_amount (con pix_key) O br_code."
                  },
                  "br_code": {
                    "type": "string",
                    "description": "Pix Copia y Pega (empieza por 000201). El importe y el destinatario proceden del código; no envíes brl_amount."
                  },
                  "funding_source": {
                    "type": "string",
                    "enum": [
                      "crypto_usdt"
                    ],
                    "description": "Opcional; solo admite crypto_usdt."
                  }
                }
              },
              "example": {
                "brl_amount": "50.00"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CotacaoPixCarteira"
                }
              }
            }
          },
          "400": {
            "description": "`valor_invalido`, `valor_abaixo_do_minimo` (min_brl), `br_code_invalido`, `campos_conflitantes`, `cotacao_recusada`, `funding_source_invalido`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/payments": {
      "post": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Pagar un Pix con el saldo USDT",
        "description": "Reserva el USDT, paga el Pix y debita lo que costó (el sobrante de la reserva vuelve). Asíncrono: responde en `reservado`; sigue GET /carteira-usdt/payments/{payment_id} o los webhooks `wallet.payment_completed` / `wallet.payment_failed`. Envía `external_id` para repetir con seguridad: el mismo external_id con los mismos datos devuelve el mismo pago (200).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "brl_amount": {
                    "type": "string",
                    "example": "50.00",
                    "description": "Importe que recibe el destinatario, en reales brasileños. Usa O brl_amount (con pix_key) O br_code."
                  },
                  "br_code": {
                    "type": "string",
                    "description": "Pix Copia y Pega (empieza por 000201). El importe y el destinatario proceden del código; no envíes brl_amount."
                  },
                  "funding_source": {
                    "type": "string",
                    "enum": [
                      "crypto_usdt"
                    ],
                    "description": "Opcional; solo admite crypto_usdt."
                  },
                  "pix_key": {
                    "type": "string",
                    "description": "Clave Pix del destinatario (obligatoria con brl_amount)."
                  },
                  "pix_key_type": {
                    "type": "string",
                    "enum": [
                      "cpf",
                      "cnpj",
                      "email",
                      "phone",
                      "random"
                    ],
                    "description": "Recomendado cuando la clave tiene 11 dígitos (CPF o teléfono)."
                  },
                  "quote_id": {
                    "type": "string",
                    "description": "Con br_code: el quote_id de la cotización (opcional)."
                  },
                  "external_id": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Tu identificador idempotente."
                  }
                }
              },
              "example": {
                "brl_amount": "50.00",
                "pix_key": "cliente@exemplo.com",
                "pix_key_type": "email",
                "external_id": "pedido-123"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pago creado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagamentoCarteira"
                }
              }
            }
          },
          "200": {
            "description": "Repetición del mismo external_id: el pago ya existente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagamentoCarteira"
                }
              }
            }
          },
          "400": {
            "description": "`valor_invalido`, `valor_abaixo_do_minimo`, `pix_key_obrigatoria`, `br_code_invalido`, `campos_conflitantes`, `cotacao_recusada`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "`saldo_insuficiente`, `external_id_divergente`, `cotacao_divergente`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Listar pagos",
        "description": "Los 100 más recientes. Los completados incluyen E2E, nombre, CPF parcial y el enlace del comprobante.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PagamentoCarteira"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/carteira-usdt/payments/{payment_id}": {
      "get": {
        "tags": [
          "Billetera USDT"
        ],
        "summary": "Hacer seguimiento de un pago",
        "description": "Estado actual del Pix pagado con USDT. Al completarse incluye E2E, nombre, CPF parcial y receipt_url.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "payment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagamentoCarteira"
                }
              }
            }
          },
          "404": {
            "description": "`nao_encontrado`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "Clave ausente o no válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`carteira_nao_liberada`: la billetera no está habilitada para este proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "503": {
            "description": "`carteira_indisponivel` / `pagamentos_indisponiveis`: vuelve a intentarlo en unos instantes (`acao: esperar`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Mínimos y máximos por moneda y red",
    "url": "https://docs.luniumpay.com/minimos"
  },
  "webhooks": {
    "evento": {
      "post": {
        "summary": "Evento que enviamos a tu endpoint",
        "description": "Configura `webhook_url` (https pública) en POST /keys o PATCH /keys/me. Responde 2xx rápidamente y procesa de forma asíncrona: cualquier respuesta fuera de 2xx provoca un reintento con espera exponencial (12 intentos, ~7h). Verifica SIEMPRE la firma. Las entregas que agotan los intentos siguen visibles en GET /webhooks/deliveries y pueden recuperarse mediante el reintento.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventoWebhook"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^sha256=[0-9a-f]{64}$"
            },
            "description": "OBSOLETA, retirada el 2026-11-09: las claves creadas a partir del 2026-08-08 no la reciben. Verifica la v2 (X-Lunium-Signature, HMAC de \"timestamp.cuerpo\", rechaza > 5 min). Hasta esa fecha, las integraciones existentes siguen recibiendo esta firma v1 (HMAC del cuerpo sin procesar) normalmente.",
            "deprecated": true
          },
          {
            "name": "X-Lunium-Signature",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^t=\\d+,v1=[0-9a-f]{64}$"
            },
            "description": "Firma v2: `t=<unix>,v1=<HMAC-SHA256 de \"<t>.<cuerpo sin procesar>\">`. Prefiere esta: como el timestamp forma parte del HMAC, puedes rechazar las entregas antiguas y una entrega capturada no puede reutilizarse contra ti después. Tolerancia recomendada: 5 minutos."
          },
          {
            "name": "X-Lunium-Event",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Nombre del evento, para enrutar sin abrir el cuerpo."
          },
          {
            "name": "X-Lunium-Event-Id",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Igual que event_id del cuerpo."
          },
          {
            "name": "X-Lunium-Delivery-Id",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Identifica este INTENTO (cambia en cada reintento). Cítalo a soporte."
          },
          {
            "name": "X-Lunium-Attempt",
            "in": "header",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Número del intento. >1 significa que ya puedes haber recibido este evento."
          },
          {
            "name": "X-Lunium-Timestamp",
            "in": "header",
            "schema": {
              "type": "integer"
            },
            "description": "Hora Unix del envío; el mismo `t` de la v2."
          }
        ],
        "responses": {
          "200": {
            "description": "Recibido. Cualquier 2xx finaliza la entrega."
          },
          "default": {
            "description": "Nao-2xx agenda nova tentativa."
          }
        }
      }
    }
  }
}
