Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.
Requiere una Membresía Silver o superior — tanto para solicitarla como para cada llamada autenticada. Si la Membresía del titular de la clave caduca, el proyecto se congela hasta que vuelva a suscribirse.
Una API REST que permite a tu aplicación trabajar con el saldo de Vito de un usuario desde dentro de Discord: leerlo, cobrarlo, abonarlo o moverlo entre usuarios. Todos los endpoints devuelven JSON y están versionados bajo /v1.
Vito nunca se convierte en dinero real ni proviene de él. Solo se mueve entre saldos de Vetox.
Todos los endpoints están bajo https://api.vetox.io/public/vito.Las rutas que aparecen en esta página — /v1/deduct, /v1/balance/:discordId y las demás — son relativas a ese prefijo, que es lo que el SDK añade por ti. Si llamas a una directamente, usa la URL completa:
https://api.vetox.io/public/vito/v1/deduct
https://api.vetox.io/v1/deduct no es una ruta y devuelve 404.
¿Desarrollas con Node.js? No escribas las llamadas REST a mano: usa el paquete oficial @vetox-bot/vito. Cubre los nueve endpoints y la verificación de webhooks, y se encarga por ti de la idempotencia y los reintentos. Consulta SDK oficial de Node.js más abajo.
Tu clave y tu secreto de firma se muestran exactamente una vez. Tras la aprobación dispones de una ventana de 7 días para revelarlos en la pestaña de claves API. Vetox solo guarda un hash y no puede volver a mostrarlos: si pierdes la ventana, tendrás que rotar.
Guárdala solo en el servidor — cualquiera que la tenga puede cobrar a tus usuarios
Rota desde la pestaña de claves API. La clave anterior sigue funcionando durante un periodo de gracia de 24 horas para que puedas desplegar sin cortes
El secreto de firma de webhooks rota por separado, con su propio solapamiento de 24 horas
El paquete oficial @vetox-bot/vito envuelve los nueve endpoints y además la verificación de webhooks. Se encarga por ti de la cabecera Idempotency-Key, de los reintentos con espera creciente, de los tiempos de espera y de clasificar los errores.
Requiere Node.js 20 o superior. El paquete no tiene ninguna dependencia en tiempo de ejecución — usa el fetch integrado y node:crypto — y se distribuye en ESM y CommonJS con definiciones completas de TypeScript.
import { VitoClient } from '@vetox-bot/vito';const vito = new VitoClient({ apiKey: process.env.VITO_API_KEY });
Si omites apiKey, el SDK lee VITO_API_KEY del entorno. El formato de la clave se valida al construir el cliente, así que una clave mal formada falla de inmediato en lugar de costarte una ida y vuelta y un 401.
La clave mueve dinero: mantenla siempre en el servidor, nunca en un bundle de cliente ni en el navegador. console.log(vito) imprime [redacted] en lugar de la clave, y el SDK rechaza cualquier baseUrl con http:// para un host no local, para que la clave no viaje en claro.
Cada método devuelve directamente el campo data ya desenvuelto: nunca tienes que desempaquetar success ni data por tu cuenta. Además, todos aceptan opciones por llamada: { timeoutMs, maxRetries, signal, headers }, y los métodos de escritura aceptan también { idempotencyKey }.
const wallet = await vito.balance.retrieve('123456789012345678');if (!wallet.hasPin) { // Todavía no tiene PIN de monedero, así que no puede confirmar ningún cobro.}
const credit = await vito.payments.credit( { discordId: '123456789012345678', amount: 250, reason: 'Reembolso del pedido order_10423', merchantRef: 'refund_10423', }, // Derivar la clave de tu propio registro hace que sea seguro relanzarlo desde // una cola de trabajos: una repetición devuelve el resultado original en lugar // de pagar dos veces. { idempotencyKey: 'refund_10423' },);console.log(credit.transactionId, credit.ownerBalance, credit.recipientBalance);
const since = Date.now() - 24 * 60 * 60 * 1000;// Un generador asíncrono que pide páginas bajo demanda: sin bucle de paginación manual.for await (const tx of vito.transactions.iterate({ limit: 100 })) { if (tx.date < since) break; // las más recientes primero // tx.type es la dirección respecto a tx.discordId: 1 = entrada, 0 = salida.}
El SDK envía una cabecera Idempotency-Key en todas las escrituras (deduct, credit, transfer). Si no le pasas ninguna, la genera una sola vez por llamada y reenvía esa misma clave en cada reintento, de modo que un reintento nunca puede liquidar la operación dos veces.Pasa tu propia clave cuando la misma operación lógica pueda reintentarse desde un proceso nuevo: un ejecutor de trabajos, una reentrega de una cola o una tarea programada:
Fallos de red, tiempos de espera, 408, 429, 5xx y 409 VITO_IDEMPOTENCY_IN_PROGRESS
Nunca se reintenta
409 VITO_IDEMPOTENCY_CONFLICT, el resto de errores 4xx y auth.rotateKey()
auth.rotateKey() queda excluido a propósito: un reintento allí emite una segunda clave e invalida la que devolvió el primer intento.
Si Retry-After es mayor que maxRetryDelayMs (es decir, tu cuota por hora está realmente agotada), el SDK lanza VitoRateLimitError de inmediato en lugar de dormir durante todo tu presupuesto de petición.
import { Webhooks, VitoSignatureVerificationError } from '@vetox-bot/vito';try { const event = Webhooks.constructEvent({ payload: rawRequestBody, // el cuerpo en bruto — mira la advertencia de abajo signature: req.header('x-vito-signature') ?? '', secret: process.env.VITO_WEBHOOK_SECRET, }); if (event.eventType === 'confirmation.completed') { // El tipo de data se estrecha automáticamente según eventType. await fulfil(event.data.merchantRef); }} catch (error) { if (error instanceof VitoSignatureVerificationError) { // Rechaza la entrega con un 400: falsificada, caducada o cuerpo reserializado. }}
constructEvent comprueba la ventana de repetición de 5 minutos, compara en tiempo constante contra todas las firmas h1 de la cabecera — por lo que funciona automáticamente durante el solapamiento de 24 horas de la rotación — y después analiza el payload y devuelve el evento tipado.En un manejador de ruta de Next.js (App Router), usa la variante que lee el cuerpo en bruto por sí misma:
export const runtime = 'nodejs'; // la verificación usa node:cryptoexport async function POST(request: Request) { const event = await Webhooks.constructEventFromRequest(request, { secret: process.env.VITO_WEBHOOK_SECRET, }); return Response.json({ received: true });}
La firma cubre los bytes en bruto. En Express, monta express.raw({ type: 'application/json' }) en la ruta del webhook: express.json() consume el cuerpo y a partir de ahí toda verificación falla. En Next.js, no llames a request.json() antes de constructEventFromRequest.
La entrega es al menos una vez. Deduplica con event.eventId antes de ejecutar cualquier efecto secundario.
Tu clave por sí sola no puede mover el Vito de un usuario. Todo cobro exige que el usuario lo apruebe con el PIN de su monedero, en vetox.io — nunca dentro de tu app ni dentro de Discord.
1
Tu app llama a POST /v1/deduct
Con el usuario, el importe, el guildId de origen y los detalles del artículo.
2
Vito devuelve una confirmUrl
Una confirmación pendiente, válida 10 minutos. El usuario también recibe un MD.
3
El usuario aprueba con su PIN
En vetox.io.
4
Vito liquida y notifica
Se descuenta el saldo, se registra la transacción y se envía un webhook firmado si tienes uno configurado.
5
Tu app verifica y completa
Comprueba la firma y luego desbloquea el contenido o entrega el artículo.
Completa tu acción solo con confirmation.completed — nunca con la respuesta de /deduct. En ese punto el cobro todavía no es definitivo.
POST /v1/add abona Vito a un usuario desde tu propio saldo, para recompensas o reembolsos. Los mismos campos que /deduct salvo guildId y product.
A diferencia de un cobro, un abono no tiene paso de confirmación: se liquida al instante. Requiere el scope credit:create y saldo suficiente, o la llamada devuelve 402 VITO_INSUFFICIENT_OWNER_FUNDS.
Cada cobro se te liquida menos la comisión de la plataforma, con el mismo esquema que las transferencias de Vito dentro de la app y según tu nivel de Membresía:
Tu Membresía
Comisión
Normal, Silver, Gold
7 %
Platinum
6 %
Diamond
5 %
Los importes de 5 Vito o menos no tienen comisión, y los abonos vía /v1/add nunca la tienen.
Añade una o varias URL de callback https en la pestaña de ajustes. Vito entrega un POST firmado cada vez que una confirmación alcanza un estado final.
Los webhooks solo se envían si tu proyecto tiene a la vez una URL de callback y un secreto de firma. Revela el secreto (whsec_…) una única vez desde la pestaña de claves API.
Acepta la entrega si coincide cualquiera de los h1. Un verificador que solo lea el primero rechazará todos los webhooks hasta haber desplegado el secreto nuevo, que es justo lo que el solapamiento de 24 horas pretende evitar.
En Node.js: Webhooks.constructEvent de @vetox-bot/vito hace todo esto por ti — la ventana de repetición, la comparación con todas las firmas h1 y el cotejo en tiempo constante — y devuelve el evento tipado. El código de abajo es para una implementación manual o para otro lenguaje.
Recalcula el HMAC sobre <ts>:<rawBody> con tu secreto de firma y compara en tiempo constante.
const crypto = require('crypto');function verify(rawBody, header, secret) { const parts = header.split(';'); const ts = parts.find(p => p.startsWith('ts='))?.slice(3); const sigs = parts.filter(p => p.startsWith('h1=')).map(p => p.slice(3)); if (!ts || sigs.length === 0) return false; // Reject anything older than ~5 minutes — replay protection. if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; const expected = Buffer.from( crypto.createHmac('sha256', secret).update(`${ts}:${rawBody}`).digest('hex'), ); // Any matching signature is valid — a rotation emits several. return sigs.some(sig => { const actual = Buffer.from(sig); // timingSafeEqual throws when the lengths differ, so check first. return ( actual.length === expected.length && crypto.timingSafeEqual(actual, expected) ); });}
Verifica contra el cuerpo en bruto, antes de cualquier parseo de JSON o middleware que lo reescriba.
También existe un límite por IP igual a la mitad de tu cuota por minuto, con un mínimo de 30.
Bajo carga, los endpoints de escritura fallan en cerrado: se rechaza el cobro en lugar de arriesgar un doble gasto. Los de lectura fallan en abierto. Trata una escritura rechazada como «no ocurrió» y reinténtala.
Envía una cabecera Idempotency-Key para deduplicar los reintentos con seguridad.
La Membresía del titular ha caducado. Se comprueba en cada llamada.
He perdido mi clave
No se puede recuperar: solo se almacena un hash. Rota para obtener una nueva.
Las firmas de webhook fallan tras rotar
Acepta ambos secretos durante el solapamiento de 24 horas.
Un cobro nunca se completa
El usuario no lo aprobó. Las confirmaciones caducan a los 10 minutos.
No llega ningún webhook
Un proyecto necesita URL de callback y secreto de firma. Con solo uno de los dos no se entrega nada.
Llegó menos Vito del que cobré
Es la comisión de liquidación. Usa importes de 5 Vito o menos para evitarla, o inclúyela en tu precio.
402 VITO_INSUFFICIENT_OWNER_FUNDS
/v1/add se financia con tu propio saldo, no se crea de la nada. Recarga.
Vito
Saldos, el PIN y las comisiones.
Solicitudes de pago
Lo que ve el usuario cuando le cobras.
@vetox-bot/vito en npm
El paquete oficial de Node.js: una instalación, integración completa.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Vetox","description":"Official documentation for Vetox — the all-in-one Discord bot for moderation, automation, leveling, tickets, giveaways, notifications and more. Trusted by over 1,000,000 servers.","colors":{"primary":"#0086FF","light":"#4DA9FF","dark":"#0067CC"},"logo":{"light":"https://vetox.io/logo.svg","dark":"https://vetox.io/logo.svg","href":"https://vetox.io"},"favicon":"https://vetox.io/logo.svg","appearance":{"default":"dark"},"navbar":{"links":[{"href":"https://vetox.io/commands","label":"Commands"},{"href":"https://discord.gg/vetox","label":"Support"}],"primary":{"type":"button","label":"Add to Discord","href":"https://discord.com/oauth2/authorize?client_id=707333425685856316\u0026permissions=8\u0026integration_type=0\u0026scope=bot"}},"footer":{"socials":{"x":"https://x.com/VetoxBot","discord":"https://discord.gg/vetox","website":"https://vetox.io"},"links":[{"header":"Product","items":[{"label":"Commands","href":"https://vetox.io/commands"},{"label":"Server Premium","href":"https://vetox.io/pricing/premium"},{"label":"Membership","href":"https://vetox.io/pricing/membership"},{"label":"Profile","href":"https://vetox.io/dashboard/overview"}]},{"header":"Support","items":[{"label":"Support Server","href":"https://discord.gg/vetox"},{"label":"Report Issue","href":"https://discord.gg/vetox"},{"label":"Contact Us","href":"https://vetox.io/contact"},{"label":"About Us","href":"https://vetox.io/about"}]},{"header":"Vito API","items":[{"label":"Documentation","href":"https://docs.vetox.io/en/members/vito-api"},{"label":"Terms","href":"https://vetox.io/vito-api-terms"}]},{"header":"Policies","items":[{"label":"Privacy Policy","href":"https://vetox.io/policy"},{"label":"Terms of Services","href":"https://vetox.io/tos"},{"label":"Refund Terms","href":"https://vetox.io/refunds"}]}]},"search":{"prompt":"Search Vetox documentation..."},"seo":{"metatags":{"og:image":"https://vetox.io/brand/vetox-header-04.png","twitter:image":"https://vetox.io/brand/vetox-header-04.png"},"indexing":"navigable"},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"styling":{"latex":false},"navigation":{"languages":[{"language":"en","href":"en"},{"language":"ar","href":"ar"},{"language":"zh-CN","href":"zh-CN"},{"language":"fr","href":"fr"},{"language":"de","href":"de"},{"language":"ja","href":"ja"},{"language":"ru","href":"ru"},{"language":"es","href":"es"},{"language":"tr","href":"tr"},{"language":"nl","href":"nl"},{"language":"pt","href":"pt"},{"language":"it","href":"it"},{"language":"pl","href":"pl"},{"language":"id","href":"id"},{"language":"hi","href":"hi"},{"language":"ko","href":"ko"},{"language":"vi","href":"vi"},{"language":"uk","href":"uk"}]}},"deployment":{"deploymentMetadataValue":{"subdomain":"vetox-ec2a2bcb","hasAudioNarration":false,"actualSubdomain":"vetox-ec2a2bcb","customDomains":["docs.vetox.io"],"gitSource":{"type":"github","owner":"iryodev","repo":"mintlify-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"latestBuiltDeploymentHistoryId":"6ac502d78f50001bddeb2024","collectionId":"31530db3-a223-4486-9cd7-7a855d38e78e","liveDeploymentHistoryId":"6ac502d78f50001bddeb2024","schemaVersion":"v3"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ac502d78f50001bddeb2024","clientVersion":"0.0.3966","searchFilterCounts":[{"language":"ar","tag":"لوحة تحكم الخادم","count":52},{"language":"de","tag":"Server-Dashboard","count":52},{"language":"en","tag":"Server Dashboard","count":52},{"language":"es","tag":"Panel del servidor","count":52},{"language":"fr","tag":"Tableau de bord serveur","count":52},{"language":"hi","tag":"सर्वर डैशबोर्ड","count":52},{"language":"id","tag":"Dasbor Server","count":52},{"language":"it","tag":"Pannello del server","count":52},{"language":"ja","tag":"サーバーダッシュボード","count":52},{"language":"ko","tag":"서버 대시보드","count":52},{"language":"nl","tag":"Serverdashboard","count":52},{"language":"pl","tag":"Panel serwera","count":52},{"language":"pt","tag":"Painel do servidor","count":52},{"language":"ru","tag":"Панель сервера","count":52},{"language":"tr","tag":"Sunucu Paneli","count":52},{"language":"uk","tag":"Панель сервера","count":52},{"language":"vi","tag":"Bảng điều khiển máy chủ","count":52},{"language":"zh-CN","tag":"服务器控制台","count":52},{"language":"ar","tag":"حسابك","count":21},{"language":"de","tag":"Dein Konto","count":21},{"language":"en","tag":"Your Account","count":21},{"language":"es","tag":"Tu cuenta","count":21},{"language":"fr","tag":"Votre compte","count":21},{"language":"hi","tag":"आपका खाता","count":21},{"language":"id","tag":"Akun Anda","count":21},{"language":"it","tag":"Il tuo account","count":21},{"language":"ja","tag":"アカウント","count":21},{"language":"ko","tag":"내 계정","count":21},{"language":"nl","tag":"Jouw account","count":21},{"language":"pl","tag":"Twoje konto","count":21},{"language":"pt","tag":"Sua conta","count":21},{"language":"ru","tag":"Ваш аккаунт","count":21},{"language":"tr","tag":"Hesabınız","count":21},{"language":"uk","tag":"Ваш обліковий запис","count":21},{"language":"vi","tag":"Tài khoản của bạn","count":21},{"language":"zh-CN","tag":"你的账户","count":21},{"language":"ar","tag":"التوثيق","count":11},{"language":"de","tag":"Dokumentation","count":11},{"language":"en","tag":"Documentation","count":11},{"language":"es","tag":"Documentación","count":11},{"language":"fr","tag":"Documentation","count":11},{"language":"hi","tag":"दस्तावेज़","count":11},{"language":"id","tag":"Dokumentasi","count":11},{"language":"it","tag":"Documentazione","count":11},{"language":"ja","tag":"ドキュメント","count":11},{"language":"ko","tag":"문서","count":11},{"language":"nl","tag":"Documentatie","count":11},{"language":"pl","tag":"Dokumentacja","count":11},{"language":"pt","tag":"Documentação","count":11},{"language":"ru","tag":"Документация","count":11},{"language":"tr","tag":"Dokümantasyon","count":11},{"language":"uk","tag":"Документація","count":11},{"language":"vi","tag":"Tài liệu","count":11},{"language":"zh-CN","tag":"文档","count":11},{"language":"ar","tag":"المجتمع","count":9},{"language":"ar","tag":"الإشعارات","count":9},{"language":"de","tag":"Community","count":9},{"language":"de","tag":"Benachrichtigungen","count":9},{"language":"en","tag":"Community","count":9},{"language":"en","tag":"Notifications","count":9},{"language":"es","tag":"Comunidad","count":9},{"language":"es","tag":"Notificaciones","count":9},{"language":"fr","tag":"Communauté","count":9},{"language":"fr","tag":"Notifications","count":9},{"language":"hi","tag":"समुदाय","count":9},{"language":"hi","tag":"सूचनाएँ","count":9},{"language":"id","tag":"Komunitas","count":9},{"language":"id","tag":"Notifikasi","count":9},{"language":"it","tag":"Comunità","count":9},{"language":"it","tag":"Notifiche","count":9},{"language":"ja","tag":"コミュニティ","count":9},{"language":"ja","tag":"通知","count":9},{"language":"ko","tag":"커뮤니티","count":9},{"language":"ko","tag":"알림","count":9},{"language":"nl","tag":"Community","count":9},{"language":"nl","tag":"Meldingen","count":9},{"language":"pl","tag":"Społeczność","count":9},{"language":"pl","tag":"Powiadomienia","count":9},{"language":"pt","tag":"Comunidade","count":9},{"language":"pt","tag":"Notificações","count":9},{"language":"ru","tag":"Сообщество","count":9},{"language":"ru","tag":"Уведомления","count":9},{"language":"tr","tag":"Topluluk","count":9},{"language":"tr","tag":"Bildirimler","count":9},{"language":"uk","tag":"Спільнота","count":9},{"language":"uk","tag":"Сповіщення","count":9},{"language":"vi","tag":"Cộng đồng","count":9},{"language":"vi","tag":"Thông báo","count":9},{"language":"zh-CN","tag":"社区","count":9},{"language":"zh-CN","tag":"通知","count":9},{"language":"ar","tag":"الرئيسية","count":8},{"language":"ar","tag":"الإدارة","count":8},{"language":"de","tag":"Hauptbereich","count":8},{"language":"de","tag":"Verwaltung","count":8},{"language":"en","tag":"Main","count":8},{"language":"en","tag":"Administration","count":8},{"language":"es","tag":"Principal","count":8},{"language":"es","tag":"Administración","count":8},{"language":"fr","tag":"Principal","count":8},{"language":"fr","tag":"Administration","count":8},{"language":"hi","tag":"मुख्य","count":8},{"language":"hi","tag":"प्रशासन","count":8},{"language":"id","tag":"Utama","count":8},{"language":"id","tag":"Administrasi","count":8},{"language":"it","tag":"Principale","count":8},{"language":"it","tag":"Amministrazione","count":8},{"language":"ja","tag":"メイン","count":8},{"language":"ja","tag":"管理","count":8},{"language":"ko","tag":"메인","count":8},{"language":"ko","tag":"관리","count":8},{"language":"nl","tag":"Hoofd","count":8},{"language":"nl","tag":"Beheer","count":8},{"language":"pl","tag":"Główne","count":8},{"language":"pl","tag":"Administracja","count":8},{"language":"pt","tag":"Principal","count":8},{"language":"pt","tag":"Administração","count":8},{"language":"ru","tag":"Основное","count":8},{"language":"ru","tag":"Администрирование","count":8},{"language":"tr","tag":"Ana","count":8},{"language":"tr","tag":"Yönetim","count":8},{"language":"uk","tag":"Головне","count":8},{"language":"uk","tag":"Адміністрування","count":8},{"language":"vi","tag":"Chính","count":8},{"language":"vi","tag":"Quản trị","count":8},{"language":"zh-CN","tag":"主要","count":8},{"language":"zh-CN","tag":"管理","count":8},{"language":"ar","tag":"الأوامر","count":7},{"language":"de","tag":"Befehle","count":7},{"language":"en","tag":"Commands","count":7},{"language":"es","tag":"Comandos","count":7},{"language":"fr","tag":"Commandes","count":7},{"language":"hi","tag":"कमांड","count":7},{"language":"id","tag":"Perintah","count":7},{"language":"it","tag":"Comandi","count":7},{"language":"ja","tag":"コマンド","count":7},{"language":"ko","tag":"명령어","count":7},{"language":"nl","tag":"Commando's","count":7},{"language":"pl","tag":"Polecenia","count":7},{"language":"pt","tag":"Comandos","count":7},{"language":"ru","tag":"Команды","count":7},{"language":"tr","tag":"Komutlar","count":7},{"language":"uk","tag":"Команди","count":7},{"language":"vi","tag":"Lệnh","count":7},{"language":"zh-CN","tag":"命令","count":7},{"language":"ar","tag":"بريميوم","count":6},{"language":"ar","tag":"التواصل","count":6},{"language":"de","tag":"Premium","count":6},{"language":"de","tag":"Kommunikation","count":6},{"language":"en","tag":"Premium","count":6},{"language":"en","tag":"Communication","count":6},{"language":"es","tag":"Premium","count":6},{"language":"es","tag":"Comunicación","count":6},{"language":"fr","tag":"Premium","count":6},{"language":"fr","tag":"Communication","count":6},{"language":"hi","tag":"प्रीमियम","count":6},{"language":"hi","tag":"संचार","count":6},{"language":"id","tag":"Premium","count":6},{"language":"id","tag":"Komunikasi","count":6},{"language":"it","tag":"Premium","count":6},{"language":"it","tag":"Comunicazione","count":6},{"language":"ja","tag":"プレミアム","count":6},{"language":"ja","tag":"コミュニケーション","count":6},{"language":"ko","tag":"프리미엄","count":6},{"language":"ko","tag":"커뮤니케이션","count":6},{"language":"nl","tag":"Premium","count":6},{"language":"nl","tag":"Communicatie","count":6},{"language":"pl","tag":"Premium","count":6},{"language":"pl","tag":"Komunikacja","count":6},{"language":"pt","tag":"Premium","count":6},{"language":"pt","tag":"Comunicação","count":6},{"language":"ru","tag":"Премиум","count":6},{"language":"ru","tag":"Общение","count":6},{"language":"tr","tag":"Premium","count":6},{"language":"tr","tag":"İletişim","count":6},{"language":"uk","tag":"Преміум","count":6},{"language":"uk","tag":"Комунікація","count":6},{"language":"vi","tag":"Premium","count":6},{"language":"vi","tag":"Giao tiếp","count":6},{"language":"zh-CN","tag":"高级版","count":6},{"language":"zh-CN","tag":"沟通","count":6}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"es/members/vito-api","slug":"/es/members/vito-api","pageMetadata":{"title":"API de Vito y compras","sidebarTitle":"API de Vito","description":"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.","icon":"code","keywords":["api de vito","compras","solicitudes de pago","desarrollador","clave api","comercio"],"href":"/es/members/vito-api"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{Accordion,AccordionGroup,Card,CardGroup,CodeBlock,Heading,Info,Note,Step,Steps,Table,Tip,Warning}=_components;if(!Accordion)_missingMdxReference(`Accordion`,true);if(!AccordionGroup)_missingMdxReference(`AccordionGroup`,true);if(!Card)_missingMdxReference(`Card`,true);if(!CardGroup)_missingMdxReference(`CardGroup`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Info)_missingMdxReference(`Info`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Info,{children:_jsxs(_components.p,{children:[`Requiere una Membresía `,_jsx(_components.strong,{children:`Silver`}),` o superior — tanto para solicitarla como para cada llamada autenticada. Si la Membresía del titular de la clave caduca, el proyecto se congela hasta que vuelva a suscribirse.`]})}),`\n`,_jsxs(_components.p,{children:[`Una API REST que permite a tu aplicación trabajar con el saldo de `,_jsx(_components.a,{href:`/es/members/vito`,children:`Vito`}),` de un usuario desde dentro de Discord: leerlo, cobrarlo, abonarlo o moverlo entre usuarios. Todos los endpoints devuelven JSON y están versionados bajo `,_jsx(_components.code,{children:`/v1`}),`.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Vito nunca se convierte en dinero real ni proviene de él.`}),` Solo se mueve entre saldos de Vetox.`]})}),`\n`,_jsxs(Warning,{children:[_jsx(_components.p,{children:_jsxs(_components.strong,{children:[`Todos los endpoints están bajo `,_jsx(_components.code,{children:`https://api.vetox.io/public/vito`}),`.`]})}),_jsxs(_components.p,{children:[`Las rutas que aparecen en esta página — `,_jsx(_components.code,{children:`/v1/deduct`}),`, `,_jsx(_components.code,{children:`/v1/balance/:discordId`}),` y las demás — son relativas a ese prefijo, que es lo que el SDK añade por ti. Si llamas a una directamente, usa la URL completa:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`https://api.vetox.io/public/vito/v1/deduct`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsxs(_components.p,{children:[_jsx(_components.code,{children:`https://api.vetox.io/v1/deduct`}),` no es una ruta y devuelve 404.`]})]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`¿Desarrollas con Node.js? No escribas las llamadas REST a mano: usa el paquete oficial `,_jsx(_components.a,{href:`https://www.npmjs.com/package/@vetox-bot/vito`,children:_jsx(_components.strong,{children:_jsx(_components.code,{children:`@vetox-bot/vito`})})}),`. Cubre los nueve endpoints y la verificación de webhooks, y se encarga por ti de la idempotencia y los reintentos. Consulta `,_jsx(_components.strong,{children:`SDK oficial de Node.js`}),` más abajo.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`obtener-acceso`,children:`Obtener acceso`}),`\n`,_jsxs(_components.p,{children:[`El acceso se concede `,_jsx(_components.strong,{children:`por proyecto`}),`. Necesitas los cuatro requisitos:`]}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Una Membresía activa, Silver o superior`,children:_jsx(_components.p,{children:`Se comprueba en cada llamada, no solo al aprobar la solicitud.`})}),_jsx(Step,{title:`Una solicitud de desarrollador aprobada`,children:_jsx(_components.p,{children:`Se envía desde la página de Vito API en tu panel. La revisa manualmente el equipo de Vetox.`})}),_jsx(Step,{title:`Los Términos para Desarrolladores de la API aceptados`,children:_jsx(_components.p,{children:`Se aceptan al enviar la solicitud.`})}),_jsx(Step,{title:`Los scopes que tu proyecto necesita`,children:_jsx(_components.p,{children:`Los concede el equipo de Vetox según lo que hayas descrito.`})})]}),`\n`,_jsx(Tip,{children:_jsx(_components.p,{children:`Sé concreto sobre qué estás construyendo y cómo almacenarás la clave. Las solicitudes vagas son las que se rechazan.`})}),`\n`,_jsx(Heading,{level:`3`,id:`scopes`,children:`Scopes`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Scope`}),_jsx(_components.th,{children:`Permite`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`balance:read`})}),_jsx(_components.td,{children:`Leer el saldo de Vito de un usuario`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`deduct:create`})}),_jsx(_components.td,{children:`Cobrar del saldo de un usuario`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`credit:create`})}),_jsx(_components.td,{children:`Añadir Vito a un usuario, financiado con tu propio saldo`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`transfer:create`})}),_jsx(_components.td,{children:`Mover Vito entre dos usuarios`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})}),_jsx(_components.td,{children:`Listar y leer las transacciones de tu proyecto`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`autenticación`,children:`Autenticación`}),`\n`,_jsx(_components.p,{children:`Envía tu clave secreta como token Bearer:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`Authorization:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` Bearer`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` vito_live_xxxxxxxxxxxxxxxx`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Dos capas opcionales refuerzan aún más un proyecto:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Lista de IP permitidas`}),` — restringe las llamadas a IP de servidor concretas`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Límites de tasa`}),` — topes por proyecto que escalan con el nivel de Membresía del titular`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`claves-rotación-y-almacenamiento`,children:`Claves, rotación y almacenamiento`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Tu clave y tu secreto de firma se muestran exactamente una vez.`}),` Tras la aprobación dispones de una `,_jsx(_components.strong,{children:`ventana de 7 días`}),` para revelarlos en la pestaña de claves API. Vetox solo guarda un hash y no puede volver a mostrarlos: si pierdes la ventana, tendrás que rotar.`]})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Guárdala `,_jsx(_components.strong,{children:`solo en el servidor`}),` — cualquiera que la tenga puede cobrar a tus usuarios`]}),`\n`,_jsxs(_components.li,{children:[`Rota desde la pestaña de claves API. La clave anterior sigue funcionando durante un `,_jsx(_components.strong,{children:`periodo de gracia de 24 horas`}),` para que puedas desplegar sin cortes`]}),`\n`,_jsx(_components.li,{children:`El secreto de firma de webhooks rota por separado, con su propio solapamiento de 24 horas`}),`\n`,_jsx(_components.li,{children:`Si se filtra, rota de inmediato`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`sdk-oficial-de-node-js`,children:`SDK oficial de Node.js`}),`\n`,_jsxs(_components.p,{children:[`El paquete oficial `,_jsx(_components.a,{href:`https://www.npmjs.com/package/@vetox-bot/vito`,children:_jsx(_components.strong,{children:_jsx(_components.code,{children:`@vetox-bot/vito`})})}),` envuelve los nueve endpoints y además la verificación de webhooks. Se encarga por ti de la cabecera `,_jsx(_components.code,{children:`Idempotency-Key`}),`, de los reintentos con espera creciente, de los tiempos de espera y de clasificar los errores.`]}),`\n`,_jsx(Heading,{level:`3`,id:`instalación`,children:`Instalación`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` @vetox-bot/vito`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Requiere `,_jsx(_components.strong,{children:`Node.js 20 o superior`}),`. El paquete `,_jsx(_components.strong,{children:`no tiene ninguna dependencia en tiempo de ejecución`}),` — usa el `,_jsx(_components.code,{children:`fetch`}),` integrado y `,_jsx(_components.code,{children:`node:crypto`}),` — y se distribuye en ESM y CommonJS con definiciones completas de TypeScript.`]}),`\n`,_jsx(Heading,{level:`3`,id:`inicialización`,children:`Inicialización`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`VitoClient`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '@vetox-bot/vito'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` vito`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` new`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` VitoClient`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`apiKey:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` process`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`env`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`VITO_API_KEY`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Si omites `,_jsx(_components.code,{children:`apiKey`}),`, el SDK lee `,_jsx(_components.code,{children:`VITO_API_KEY`}),` del entorno. El formato de la clave se valida al construir el cliente, así que una clave mal formada falla de inmediato en lugar de costarte una ida y vuelta y un 401.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`La clave mueve dinero: mantenla siempre en el servidor, nunca en un bundle de cliente ni en el navegador. `,_jsx(_components.code,{children:`console.log(vito)`}),` imprime `,_jsx(_components.code,{children:`[redacted]`}),` en lugar de la clave, y el SDK rechaza cualquier `,_jsx(_components.code,{children:`baseUrl`}),` con `,_jsx(_components.code,{children:`http://`}),` para un host no local, para que la clave no viaje en claro.`]})}),`\n`,_jsx(Heading,{level:`4`,id:`opciones-del-cliente`,children:`Opciones del cliente`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Opción`}),_jsx(_components.th,{children:`Por defecto`}),_jsx(_components.th,{children:`Qué hace`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`apiKey`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`process.env.VITO_API_KEY`})}),_jsxs(_components.td,{children:[`Clave del proyecto (`,_jsx(_components.code,{children:`vito_live_…`}),`)`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`baseUrl`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`https://api.vetox.io`})}),_jsx(_components.td,{children:`Raíz de la API`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`timeoutMs`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`15000`})}),_jsx(_components.td,{children:`Tiempo de espera por petición`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`maxRetries`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`2`})}),_jsx(_components.td,{children:`Reintentos ante fallos transitorios`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`retryBaseDelayMs`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`500`})}),_jsx(_components.td,{children:`Primera espera antes de reintentar; se duplica en cada reintento`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`maxRetryDelayMs`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`8000`})}),_jsxs(_components.td,{children:[`Tope de la espera y umbral de corte para `,_jsx(_components.code,{children:`Retry-After`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`fetch`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`globalThis.fetch`})}),_jsx(_components.td,{children:`Implementación propia a través de proxy o agente`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`onResponse`})}),_jsx(_components.td,{children:`—`}),_jsxs(_components.td,{children:[`Se llama tras cada respuesta, con `,_jsx(_components.code,{children:`requestId`}),`, la cuota de límite de tasa y la duración`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`onRetry`})}),_jsx(_components.td,{children:`—`}),_jsx(_components.td,{children:`Se llama antes de cada reintento`})]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`métodos-disponibles`,children:`Métodos disponibles`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Método`}),_jsx(_components.th,{children:`Endpoint`}),_jsx(_components.th,{children:`Scope`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.auth.verify()`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/auth/verify`})}),_jsx(_components.td,{children:`cualquiera`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.auth.rotateKey()`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/auth/rotate-key`})}),_jsx(_components.td,{children:`cualquiera`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.balance.retrieve(discordId)`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/balance/:discordId`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`balance:read`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.payments.deduct(params)`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/deduct`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`deduct:create`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.payments.credit(params)`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/add`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`credit:create`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.payments.transfer(params)`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/transfer`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transfer:create`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.transactions.list({ page, limit })`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/transactions`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.transactions.iterate({ limit, maxPages })`})}),_jsx(_components.td,{children:`paginación automática`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.transactions.retrieve(id)`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/transactions/:id`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.webhookEvents.list({ page, limit })`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/webhooks/events`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.webhookEvents.iterate({ limit, maxPages })`})}),_jsx(_components.td,{children:`paginación automática`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`Webhooks.constructEvent(…)`})}),_jsx(_components.td,{children:`— (verificación local)`}),_jsx(_components.td,{children:`—`})]})]})]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Cada método devuelve directamente el campo `,_jsx(_components.code,{children:`data`}),` ya desenvuelto: nunca tienes que desempaquetar `,_jsx(_components.code,{children:`success`}),` ni `,_jsx(_components.code,{children:`data`}),` por tu cuenta. Además, todos aceptan opciones por llamada: `,_jsx(_components.code,{children:`{ timeoutMs, maxRetries, signal, headers }`}),`, y los métodos de escritura aceptan también `,_jsx(_components.code,{children:`{ idempotencyKey }`}),`.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`ejemplos-de-uso`,children:`Ejemplos de uso`}),`\n`,_jsx(Heading,{level:`4`,id:`comprobar-la-clave-al-arrancar`,children:`Comprobar la clave al arrancar`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` project`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`auth`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`verify`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`console`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`project`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`status`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// \"active\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`console`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`project`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`scopes`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// [\"balance:read\", \"deduct:create\", …]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`console`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`project`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`rateLimit`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// { tier, requestsPerMinute, requestsPerHour }`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`4`,id:`leer-un-saldo`,children:`Leer un saldo`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` wallet`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`balance`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`retrieve`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'123456789012345678'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`!`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`wallet`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`hasPin`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Todavía no tiene PIN de monedero, así que no puede confirmar ningún cobro.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`4`,id:`cobrar-a-un-usuario-vender-un-artículo`,children:`Cobrar a un usuario (vender un artículo)`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`17`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`17`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` confirmation`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`payments`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`deduct`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` discordId:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '123456789012345678'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` guildId:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '987654321098765432'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` amount:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 250`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` reason:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'Espada legendaria'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` merchantRef:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'order_10423'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` metadata:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`sku:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'sword-legendary'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` product:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` type:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'virtual_item'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` name:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'Espada legendaria'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` description:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'Inflige 120 de daño.'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` imageUrl:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'https://cdn.example.com/sword.png'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`});`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`console`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`confirmation`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`confirmUrl`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// envía aquí al usuario`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`console`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`confirmation`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`expiresAt`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// unix ms, dentro de 10 minutos`})]}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Registra el pedido aquí solo como `,_jsx(_components.strong,{children:`pendiente`}),`. El cobro todavía no ha ocurrido: entrega con el webhook `,_jsx(_components.code,{children:`confirmation.completed`}),`, no con esta respuesta.`]})}),`\n`,_jsx(Heading,{level:`4`,id:`abonar-vito-a-un-usuario`,children:`Abonar Vito a un usuario`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`14`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`14`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` credit`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`payments`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`credit`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` discordId:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '123456789012345678'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` amount:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 250`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` reason:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'Reembolso del pedido order_10423'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` merchantRef:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'refund_10423'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Derivar la clave de tu propio registro hace que sea seguro relanzarlo desde`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // una cola de trabajos: una repetición devuelve el resultado original en lugar`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // de pagar dos veces.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`idempotencyKey:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'refund_10423'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`console`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`credit`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`transactionId`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`credit`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`ownerBalance`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`credit`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`recipientBalance`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`4`,id:`recorrer-las-transacciones`,children:`Recorrer las transacciones`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`7`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` since`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Date`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`now`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`-`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 24`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 60`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 60`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` *`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1000`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Un generador asíncrono que pide páginas bajo demanda: sin bucle de paginación manual.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` tx`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` of`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`transactions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`iterate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`limit:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 100`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` })) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`tx`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`date`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` since`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`break`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`; `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// las más recientes primero`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // tx.type es la dirección respecto a tx.discordId: 1 = entrada, 0 = salida.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`idempotencia-y-reintentos`,children:`Idempotencia y reintentos`}),`\n`,_jsxs(_components.p,{children:[`El SDK envía una cabecera `,_jsx(_components.code,{children:`Idempotency-Key`}),` en `,_jsx(_components.strong,{children:`todas las escrituras`}),` (`,_jsx(_components.code,{children:`deduct`}),`, `,_jsx(_components.code,{children:`credit`}),`, `,_jsx(_components.code,{children:`transfer`}),`). Si no le pasas ninguna, la genera `,_jsx(_components.strong,{children:`una sola vez por llamada y reenvía esa misma clave en cada reintento`}),`, de modo que un reintento nunca puede liquidar la operación dos veces.`]}),`\n`,_jsxs(_components.p,{children:[`Pasa tu propia clave cuando la misma operación lógica pueda reintentarse desde un `,_jsx(_components.strong,{children:`proceso nuevo`}),`: un ejecutor de trabajos, una reentrega de una cola o una tarea programada:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`payments`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`credit`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`params`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`idempotencyKey:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:\" `refund_\"}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#569CD6`},children:\"${\"}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`orderId`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#569CD6`},children:`}`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:\"`\"}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})]}),`\n`]})})}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Comportamiento`}),_jsx(_components.th,{children:`Casos`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Se reintenta automáticamente`}),_jsxs(_components.td,{children:[`Fallos de red, tiempos de espera, `,_jsx(_components.code,{children:`408`}),`, `,_jsx(_components.code,{children:`429`}),`, `,_jsx(_components.code,{children:`5xx`}),` y `,_jsx(_components.code,{children:`409 VITO_IDEMPOTENCY_IN_PROGRESS`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Nunca se reintenta`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`409 VITO_IDEMPOTENCY_CONFLICT`}),`, el resto de errores `,_jsx(_components.code,{children:`4xx`}),` y `,_jsx(_components.code,{children:`auth.rotateKey()`})]})]})]})]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`auth.rotateKey()`}),` queda excluido a propósito: un reintento allí emite una segunda clave e invalida la que devolvió el primer intento.`]})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Si `,_jsx(_components.code,{children:`Retry-After`}),` es mayor que `,_jsx(_components.code,{children:`maxRetryDelayMs`}),` (es decir, tu cuota por hora está realmente agotada), el SDK lanza `,_jsx(_components.code,{children:`VitoRateLimitError`}),` de inmediato en lugar de dormir durante todo tu presupuesto de petición.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`verificar-webhooks-con-el-sdk`,children:`Verificar webhooks con el SDK`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`18`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`18`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Webhooks`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`VitoSignatureVerificationError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '@vetox-bot/vito'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`try`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` event`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Webhooks`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`constructEvent`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` payload:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` rawRequestBody`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// el cuerpo en bruto — mira la advertencia de abajo`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` signature:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` req`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`header`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'x-vito-signature'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`??`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` ''`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` secret:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` process`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`env`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`VITO_WEBHOOK_SECRET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`event`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`eventType`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ===`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'confirmation.completed'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // El tipo de data se estrecha automáticamente según eventType.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` fulfil`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`event`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`data`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`merchantRef`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`} `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`catch`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` instanceof`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` VitoSignatureVerificationError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Rechaza la entrega con un 400: falsificada, caducada o cuerpo reserializado.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`constructEvent`}),` comprueba la ventana de repetición de 5 minutos, compara en tiempo constante contra `,_jsx(_components.strong,{children:`todas`}),` las firmas `,_jsx(_components.code,{children:`h1`}),` de la cabecera — por lo que funciona automáticamente durante el solapamiento de 24 horas de la rotación — y después analiza el payload y devuelve el evento tipado.`]}),`\n`,_jsx(_components.p,{children:`En un manejador de ruta de Next.js (App Router), usa la variante que lee el cuerpo en bruto por sí misma:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`export`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` runtime`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'nodejs'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`; `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// la verificación usa node:crypto`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`export`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` async`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` function`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` POST`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`request`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` Request`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` event`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Webhooks`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`constructEventFromRequest`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`request`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` secret:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` process`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`env`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`VITO_WEBHOOK_SECRET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Response`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`json`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`received:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`La firma cubre los `,_jsx(_components.strong,{children:`bytes en bruto`}),`. En Express, monta `,_jsx(_components.code,{children:`express.raw({ type: 'application/json' })`}),` en la ruta del webhook: `,_jsx(_components.code,{children:`express.json()`}),` consume el cuerpo y a partir de ahí toda verificación falla. En Next.js, no llames a `,_jsx(_components.code,{children:`request.json()`}),` antes de `,_jsx(_components.code,{children:`constructEventFromRequest`}),`.`]})}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`La entrega es `,_jsx(_components.strong,{children:`al menos una vez`}),`. Deduplica con `,_jsx(_components.code,{children:`event.eventId`}),` antes de ejecutar cualquier efecto secundario.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`gestión-de-errores`,children:`Gestión de errores`}),`\n`,_jsxs(_components.p,{children:[`Todo lo que lanza el SDK hereda de `,_jsx(_components.code,{children:`VitoError`}),` y lleva `,_jsx(_components.code,{children:`code`}),`, `,_jsx(_components.code,{children:`status`}),`, `,_jsx(_components.code,{children:`type`}),`, `,_jsx(_components.code,{children:`requestId`}),` y `,_jsx(_components.code,{children:`retryable`}),`.`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Clase`}),_jsx(_components.th,{children:`Estado`}),_jsx(_components.th,{children:`Cuándo`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoInvalidRequestError`})}),_jsx(_components.td,{children:`—`}),_jsxs(_components.td,{children:[`Argumentos rechazados `,_jsx(_components.strong,{children:`antes`}),` de enviar ninguna petición`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoConfigurationError`})}),_jsx(_components.td,{children:`—`}),_jsxs(_components.td,{children:[`Clave ausente o mal formada, o `,_jsx(_components.code,{children:`baseUrl`}),` inservible`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoValidationError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`400`}),_jsx(_components.td,{children:`La API rechazó el cuerpo o los parámetros`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoAuthenticationError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`401`}),_jsx(_components.td,{children:`Clave inválida o revocada`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoInsufficientFundsError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`402`}),_jsx(_components.td,{children:`El monedero no cubre el importe (usuario o titular)`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoPermissionError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`Falta scope, IP, términos, congelación, servidor no permitido o Membresía caducada`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoNotFoundError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`404`}),_jsx(_components.td,{children:`Usuario, transacción o confirmación inexistente`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoConflictError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`409`}),_jsx(_components.td,{children:`Conflicto de idempotencia, o una petición aún en curso`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoGoneError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`410`}),_jsx(_components.td,{children:`La ventana de confirmación ya venció`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoRateLimitError`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`429`}),_jsxs(_components.td,{children:[`Límite superado — incluye `,_jsx(_components.code,{children:`retryAfterSeconds`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoServerError`})}),_jsx(_components.td,{children:`5xx`}),_jsx(_components.td,{children:`Fallo por nuestra parte`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoConnectionError`})}),_jsx(_components.td,{children:`—`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`VITO_SDK_TIMEOUT`}),`, `,_jsx(_components.code,{children:`VITO_SDK_CONNECTION`}),` o `,_jsx(_components.code,{children:`VITO_SDK_ABORTED`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VitoSignatureVerificationError`})}),_jsx(_components.td,{children:`—`}),_jsx(_components.td,{children:`Falló la verificación de la firma de un webhook`})]})]})]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`12`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`12`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`isVitoError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`VitoInsufficientFundsError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '@vetox-bot/vito'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`try`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`payments`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`deduct`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`params`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`} `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`catch`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` instanceof`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` VitoInsufficientFundsError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`return`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` notEnoughVito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`isVitoError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` logger`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`code:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`code`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`requestId:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`requestId`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` throw`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` error`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`Registra siempre el `,_jsx(_components.code,{children:`requestId`}),`: es lo que necesita el soporte para rastrear una llamada concreta.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`cancelar-una-llamada`,children:`Cancelar una llamada`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` controller`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` new`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` AbortController`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`setTimeout`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`=>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` controller`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`abort`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(), `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`2000`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` vito`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`balance`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`retrieve`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`id`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`signal:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` controller`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`signal`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Cancelar detiene también cualquier reintento pendiente y lanza `,_jsx(_components.code,{children:`VitoConnectionError`}),` con el código `,_jsx(_components.code,{children:`VITO_SDK_ABORTED`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`cobrar-a-un-usuario`,children:`Cobrar a un usuario`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Tu clave por sí sola no puede mover el Vito de un usuario.`}),` Todo cobro exige que el usuario lo apruebe con el PIN de su monedero, en `,_jsx(_components.code,{children:`vetox.io`}),` — nunca dentro de tu app ni dentro de Discord.`]})}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Tu app llama a POST /v1/deduct`,children:_jsxs(_components.p,{children:[`Con el usuario, el importe, el `,_jsx(_components.code,{children:`guildId`}),` de origen y los detalles del artículo.`]})}),_jsx(Step,{title:`Vito devuelve una confirmUrl`,children:_jsxs(_components.p,{children:[`Una confirmación pendiente, válida `,_jsx(_components.strong,{children:`10 minutos`}),`. El usuario también recibe un MD.`]})}),_jsx(Step,{title:`El usuario aprueba con su PIN`,children:_jsxs(_components.p,{children:[`En `,_jsx(_components.code,{children:`vetox.io`}),`.`]})}),_jsx(Step,{title:`Vito liquida y notifica`,children:_jsx(_components.p,{children:`Se descuenta el saldo, se registra la transacción y se envía un webhook firmado si tienes uno configurado.`})}),_jsx(Step,{title:`Tu app verifica y completa`,children:_jsx(_components.p,{children:`Comprueba la firma y luego desbloquea el contenido o entrega el artículo.`})})]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsxs(_components.strong,{children:[`Completa tu acción solo con `,_jsx(_components.code,{children:`confirmation.completed`})]}),` — nunca con la respuesta de `,_jsx(_components.code,{children:`/deduct`}),`. En ese punto el cobro todavía no es definitivo.`]})}),`\n`,_jsxs(Heading,{level:`3`,id:`parámetros-de-la-petición-—-/v1/deduct`,children:[`Parámetros de la petición — `,_jsx(_components.code,{children:`/v1/deduct`})]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Campo`}),_jsx(_components.th,{children:`Obligatorio`}),_jsx(_components.th,{children:`Notas`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`discordId`})}),_jsx(_components.td,{children:_jsx(_components.strong,{children:`Sí`})}),_jsx(_components.td,{children:`El ID de Discord del usuario — un snowflake de 17 a 20 dígitos`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`amount`})}),_jsx(_components.td,{children:_jsx(_components.strong,{children:`Sí`})}),_jsx(_components.td,{children:`Entero positivo`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`guildId`})}),_jsx(_components.td,{children:_jsx(_components.strong,{children:`Sí`})}),_jsx(_components.td,{children:`El servidor de Discord del que parte el cobro. Todo cobro debe originarse en un servidor`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`reason`})}),_jsx(_components.td,{children:`No`}),_jsx(_components.td,{children:`Hasta 256 caracteres. Se muestra al usuario y se devuelve en el webhook`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`merchantRef`})}),_jsx(_components.td,{children:`No`}),_jsx(_components.td,{children:`Tu propia referencia, hasta 128 caracteres. Úsala para casar el webhook con tus registros`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`product`})}),_jsx(_components.td,{children:`No`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`{ type, name, description?, imageUrl? }`}),` — aparece en la página de confirmación y en el MD`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`imageUrl`})}),_jsx(_components.td,{children:`No`}),_jsxs(_components.td,{children:[`Debe ser `,_jsx(_components.code,{children:`https://`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`metadata`})}),_jsx(_components.td,{children:`No`}),_jsxs(_components.td,{children:[`Hasta `,_jsx(_components.strong,{children:`10`}),` pares clave/valor de texto, que se transmiten tal cual`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`abonar-vito-a-un-usuario-2`,children:`Abonar Vito a un usuario`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`POST /v1/add`}),` abona Vito a un usuario `,_jsx(_components.strong,{children:`desde tu propio saldo`}),`, para recompensas o reembolsos. Los mismos campos que `,_jsx(_components.code,{children:`/deduct`}),` salvo `,_jsx(_components.code,{children:`guildId`}),` y `,_jsx(_components.code,{children:`product`}),`.`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`A diferencia de un cobro, un abono `,_jsx(_components.strong,{children:`no tiene paso de confirmación`}),`: se liquida al instante. Requiere el scope `,_jsx(_components.code,{children:`credit:create`}),` y saldo suficiente, o la llamada devuelve `,_jsxs(_components.strong,{children:[`402 `,_jsx(_components.code,{children:`VITO_INSUFFICIENT_OWNER_FUNDS`})]}),`.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`comisiones`,children:`Comisiones`}),`\n`,_jsxs(_components.p,{children:[`Cada cobro se te liquida menos la comisión de la plataforma, con el mismo esquema que las transferencias de Vito dentro de la app y según `,_jsx(_components.strong,{children:`tu`}),` nivel de Membresía:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Tu Membresía`}),_jsx(_components.th,{children:`Comisión`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Normal, Silver, Gold`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`7 %`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Platinum`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`6 %`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Diamond`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`5 %`})]})]})]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Los importes de `,_jsx(_components.strong,{children:`5 Vito o menos no tienen comisión`}),`, y los abonos vía `,_jsx(_components.code,{children:`/v1/add`}),` nunca la tienen.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`webhooks`,children:`Webhooks`}),`\n`,_jsxs(_components.p,{children:[`Añade una o varias URL de callback `,_jsx(_components.code,{children:`https`}),` en la pestaña de ajustes. Vito entrega un `,_jsx(_components.code,{children:`POST`}),` firmado cada vez que una confirmación alcanza un estado final.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Los webhooks solo se envían si tu proyecto tiene `,_jsx(_components.strong,{children:`a la vez`}),` una URL de callback `,_jsx(_components.strong,{children:`y`}),` un secreto de firma. Revela el secreto (`,_jsx(_components.code,{children:`whsec_…`}),`) una única vez desde la pestaña de claves API.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`verificar-la-firma`,children:`Verificar la firma`}),`\n`,_jsxs(_components.p,{children:[`Cada entrega lleva una cabecera `,_jsx(_components.code,{children:`X-Vito-Signature`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`X-Vito-Signature: ts=\u003cunix>;h1=\u003chex>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`Otras dos cabeceras acompañan cada entrega — usa `,_jsx(_components.code,{children:`X-Vito-Event-Id`}),` como clave de deduplicación, ya que un reintento reenvía el mismo id:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Cabecera`}),_jsx(_components.th,{children:`Contiene`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`X-Vito-Event-Id`})}),_jsx(_components.td,{children:`Id estable de este evento — idéntico en todos los reintentos`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`X-Vito-Event-Type`})}),_jsxs(_components.td,{children:[`Por ejemplo `,_jsx(_components.code,{children:`confirmation.completed`})]})]})]})]}),`\n`,_jsxs(Warning,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Durante una rotación del secreto de firma la cabecera lleva más de una firma`}),`, la más nueva primero:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`X-Vito-Signature: ts=\u003cunix>;h1=\u003cnueva>;h1=\u003cantigua>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsxs(_components.p,{children:[`Acepta la entrega si coincide `,_jsx(_components.strong,{children:`cualquiera`}),` de los `,_jsx(_components.code,{children:`h1`}),`. Un verificador que solo lea el primero rechazará todos los webhooks hasta haber desplegado el secreto nuevo, que es justo lo que el solapamiento de 24 horas pretende evitar.`]})]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`En Node.js: `,_jsx(_components.code,{children:`Webhooks.constructEvent`}),` de `,_jsx(_components.a,{href:`https://www.npmjs.com/package/@vetox-bot/vito`,children:_jsx(_components.code,{children:`@vetox-bot/vito`})}),` hace todo esto por ti — la ventana de repetición, la comparación con `,_jsx(_components.strong,{children:`todas`}),` las firmas `,_jsx(_components.code,{children:`h1`}),` y el cotejo en tiempo constante — y devuelve el evento tipado. El código de abajo es para una implementación manual o para otro lenguaje.`]})}),`\n`,_jsxs(_components.p,{children:[`Recalcula el HMAC sobre `,_jsx(_components.code,{children:`\u003cts>:\u003crawBody>`}),` con tu secreto de firma y compara en tiempo constante.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`24`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`24`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` crypto`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` require`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'crypto'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`function`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` verify`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`rawBody`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`header`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`secret`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` parts`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` header`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`split`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`';'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` ts`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` parts`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`find`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`p`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` =>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`startsWith`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'ts='`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`))?.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`slice`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`3`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` sigs`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` parts`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`filter`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`p`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` =>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`startsWith`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'h1='`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)).`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`map`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`p`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` =>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`slice`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`3`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`));`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`!`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`ts`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ||`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` sigs`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`length`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ===`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`return`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Reject anything older than ~5 minutes — replay protection.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Math`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`abs`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Date`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`now`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`/`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1000`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` -`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` Number`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`ts`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 300`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`return`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` expected`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Buffer`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` crypto`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`createHmac`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'sha256'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`secret`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`).`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`update`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:\"`\"}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#569CD6`},children:\"${\"}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`ts`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#569CD6`},children:`}`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#569CD6`},children:\"${\"}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`rawBody`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#569CD6`},children:`}`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:\"`\"}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`).`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`digest`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'hex'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`),`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` );`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Any matching signature is valid — a rotation emits several.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` sigs`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`some`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`sig`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` =>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` actual`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` Buffer`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`sig`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // timingSafeEqual throws when the lengths differ, so check first.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` actual`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`length`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ===`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` expected`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`length`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u0026\u0026`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` crypto`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`timingSafeEqual`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`actual`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`expected`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` );`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Verifica contra el `,_jsx(_components.strong,{children:`cuerpo en bruto`}),`, antes de cualquier parseo de JSON o middleware que lo reescriba.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`eventos`,children:`Eventos`}),`\n`,_jsxs(_components.p,{children:[`Cinco tipos de evento, todos con la misma forma de payload. `,_jsx(_components.code,{children:`data.status`}),` lleva el resultado.`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Evento`}),_jsx(_components.th,{children:`Significado`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`confirmation.completed`})}),_jsxs(_components.td,{children:[`Aprobado y cobrado. Incluye `,_jsx(_components.code,{children:`transactionId`}),`. `,_jsx(_components.strong,{children:`Completa tu acción aquí`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`confirmation.failed`})}),_jsxs(_components.td,{children:[`No se pudo completar — saldo insuficiente o error interno. Incluye `,_jsx(_components.code,{children:`failureReason`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`confirmation.expired`})}),_jsx(_components.td,{children:`No se confirmó en 10 minutos. No se movió ningún Vito`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`confirmation.cancelled`})}),_jsx(_components.td,{children:`El usuario lo canceló. No se movió ningún Vito`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`credit.completed`})}),_jsxs(_components.td,{children:[`Se liquidó un `,_jsx(_components.code,{children:`/add`}),` financiado por el titular. Se dispara al instante, sin paso de confirmación`]})]})]})]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Los webhooks se reintentan `,_jsx(_components.strong,{children:`5 veces con espera creciente`}),`. Responde 2xx rápido y haz tu entrega de forma asíncrona.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`códigos-de-error`,children:`Códigos de error`}),`\n`,_jsxs(_components.p,{children:[`Toda respuesta va envuelta. Un éxito lleva `,_jsx(_components.code,{children:`data`}),` y un fallo lleva `,_jsx(_components.code,{children:`error`}),`, nunca ambos:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`10`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`10`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"success\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"error\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Forbidden\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"message\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"API key lacks the required scope for this operation.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"code\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"VITO_INSUFFICIENT_SCOPE\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"requestId\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"…\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"timestamp\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1735161600000`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsxs(_components.strong,{children:[`Todos los códigos llevan el prefijo `,_jsx(_components.code,{children:`VITO_`}),`.`]}),` Compara la cadena completa: un `,_jsx(_components.code,{children:`RATE_LIMITED`}),` o `,_jsx(_components.code,{children:`FORBIDDEN`}),` a secas nunca aparece en la respuesta.`]})}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Código`}),_jsx(_components.th,{children:`Estado`}),_jsx(_components.th,{children:`Significado`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_VALIDATION_ERROR`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`400`}),_jsx(_components.td,{children:`Falta un campo o tiene un formato incorrecto`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_INVALID_AMOUNT`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`400`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`amount`}),` no es un entero positivo`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_AMOUNT_LIMIT_EXCEEDED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`400`}),_jsx(_components.td,{children:`Supera tu tope por transacción`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_DAILY_VOLUME_EXCEEDED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`400`}),_jsx(_components.td,{children:`Esta llamada rebasaría tu tope de volumen diario`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_SELF_TRANSFER`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`400`}),_jsx(_components.td,{children:`Emisor y receptor son el mismo usuario`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_INVALID_API_KEY`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`401`}),_jsx(_components.td,{children:`Clave ausente, mal formada, revocada o desconocida`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_INSUFFICIENT_FUNDS`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`402`}),_jsx(_components.td,{children:`El usuario no puede cubrir el cobro`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_INSUFFICIENT_OWNER_FUNDS`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`402`}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Tu`}),` saldo es insuficiente para financiar un `,_jsx(_components.code,{children:`/add`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_INSUFFICIENT_SCOPE`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`La clave no tiene el scope que exige el endpoint`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_IP_NOT_ALLOWED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`La IP que llama no está en la lista de permitidas`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_OWNER_MEMBERSHIP_INACTIVE`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`La Membresía del titular caducó — congelado hasta que se resuscriba`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_GUILD_NOT_ALLOWED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`guildId`}),` no está en la lista de servidores permitidos del proyecto`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_TOS_NOT_ACCEPTED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`Términos para desarrolladores no aceptados, o hay una versión más reciente pendiente`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_PROJECT_FROZEN`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`Congelado — normalmente por una Membresía del titular caducada`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_PROJECT_SUSPENDED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`Suspendido por el equipo de Vetox`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_PROJECT_BANNED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`Baneado por el equipo de Vetox`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_USER_BLACKLISTED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`El usuario está excluido de las operaciones con Vito`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_ACCOUNT_LOCKED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`403`}),_jsx(_components.td,{children:`El monedero del usuario está bloqueado tras intentos fallidos de PIN`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_USER_NOT_FOUND`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`404`}),_jsx(_components.td,{children:`No hay cuenta de Vito para ese ID de Discord`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_CONFIRMATION_NOT_FOUND`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`404`}),_jsx(_components.td,{children:`Token de confirmación desconocido`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_IDEMPOTENCY_CONFLICT`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`409`}),_jsxs(_components.td,{children:[`Mismo `,_jsx(_components.code,{children:`Idempotency-Key`}),` con un cuerpo distinto`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_IDEMPOTENCY_IN_PROGRESS`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`409`}),_jsx(_components.td,{children:`Una petición idéntica sigue en curso — reinténtalo en breve`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_CONFIRMATION_ALREADY_PROCESSED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`409`}),_jsx(_components.td,{children:`Esa confirmación ya alcanzó un estado final`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_KEY_ROTATION_IN_PROGRESS`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`409`}),_jsx(_components.td,{children:`Ya hay una rotación en marcha`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_CONFIRMATION_EXPIRED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`410`}),_jsx(_components.td,{children:`Transcurrió la ventana de 10 minutos`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_RATE_LIMITED`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`429`}),_jsx(_components.td,{children:`Reduce el ritmo y reinténtalo`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`VITO_INTERNAL_ERROR`})}),_jsx(_components.td,{\"data-numeric\":`true`,children:`500`}),_jsx(_components.td,{children:`Fallo inesperado por nuestra parte`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`límites-de-tasa`,children:`Límites de tasa`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Membresía del titular`}),_jsx(_components.th,{children:`Por minuto`}),_jsx(_components.th,{children:`Por hora`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Ninguna`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`60`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`1.000`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Silver o Gold`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`180`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`5.000`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Platinum o Diamond`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`600`}),_jsx(_components.td,{\"data-numeric\":`true`,children:`15.000`})]})]})]}),`\n`,_jsx(_components.p,{children:`También existe un límite por IP igual a la mitad de tu cuota por minuto, con un mínimo de 30.`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Bajo carga, `,_jsx(_components.strong,{children:`los endpoints de escritura fallan en cerrado`}),`: se rechaza el cobro en lugar de arriesgar un doble gasto. Los de lectura fallan en abierto. Trata una escritura rechazada como «no ocurrió» y reinténtala.`]})}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Envía una cabecera `,_jsx(_components.code,{children:`Idempotency-Key`}),` para deduplicar los reintentos con seguridad.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`endpoints`,children:`Endpoints`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Endpoint`}),_jsx(_components.th,{children:`Scope`}),_jsx(_components.th,{children:`Método del SDK`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/auth/verify`})}),_jsx(_components.td,{children:`cualquiera`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.auth.verify()`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/auth/rotate-key`})}),_jsx(_components.td,{children:`cualquiera`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.auth.rotateKey()`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/balance/:discordId`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`balance:read`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.balance.retrieve(id)`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/deduct`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`deduct:create`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.payments.deduct(params)`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/add`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`credit:create`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.payments.credit(params)`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`POST /v1/transfer`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transfer:create`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.payments.transfer(params)`})})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`GET /v1/transactions`}),` y `,_jsx(_components.code,{children:`/:id`})]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`vito.transactions.list()`}),` / `,_jsx(_components.code,{children:`.retrieve(id)`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`GET /v1/webhooks/events`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`transactions:read`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`vito.webhookEvents.list()`})})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`límites`,children:`Límites`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Las confirmaciones caducan a los `,_jsx(_components.strong,{children:`10 minutos`}),` — trata las no confirmadas como abandonadas`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`amount`}),` debe ser un entero positivo`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`metadata`}),` está limitado a 10 claves`]}),`\n`,_jsx(_components.li,{children:`Los topes por transacción y diarios los fija el equipo de Vetox y aparecen en modo lectura en la pestaña de ajustes`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`lista-de-comprobación-de-seguridad`,children:`Lista de comprobación de seguridad`}),`\n`,_jsxs(AccordionGroup,{children:[_jsx(Accordion,{title:`Mantén los secretos en el servidor`,icon:`lock`,id:`manten-los-secretos-en-el-servidor`,children:_jsx(_components.p,{children:`La clave API y el secreto de firma jamás deben estar en código de cliente. Rota de inmediato si alguno se filtra.`})}),_jsx(Accordion,{title:`Verifica cada webhook`,icon:`signature`,id:`verifica-cada-webhook`,children:_jsx(_components.p,{children:`Comprueba la firma contra el cuerpo en bruto y rechaza las entregas de más de ~5 minutos.`})}),_jsx(Accordion,{title:`Liquida solo con completed`,icon:`circle-check`,id:`liquida-solo-con-completed`,children:_jsxs(_components.p,{children:[`Nunca entregues basándote en la respuesta de `,_jsx(_components.code,{children:`/deduct`}),`: el cobro no es firme hasta `,_jsx(_components.code,{children:`confirmation.completed`}),`.`]})}),_jsx(Accordion,{title:`Mínimo privilegio`,icon:`key`,id:`minimo-privilegio`,children:_jsx(_components.p,{children:`Pide solo los scopes que realmente usas y activa la lista de IP permitidas.`})})]}),`\n`,_jsx(Heading,{level:`2`,id:`resolución-de-problemas`,children:`Resolución de problemas`}),`\n`,_jsxs(AccordionGroup,{children:[_jsx(Accordion,{title:`Todas las llamadas devuelven no autorizado`,id:`todas-las-llamadas-devuelven-no-autorizado`,children:_jsx(_components.p,{children:`La Membresía del titular ha caducado. Se comprueba en cada llamada.`})}),_jsx(Accordion,{title:`He perdido mi clave`,id:`he-perdido-mi-clave`,children:_jsx(_components.p,{children:`No se puede recuperar: solo se almacena un hash. Rota para obtener una nueva.`})}),_jsx(Accordion,{title:`Las firmas de webhook fallan tras rotar`,id:`las-firmas-de-webhook-fallan-tras-rotar`,children:_jsx(_components.p,{children:`Acepta ambos secretos durante el solapamiento de 24 horas.`})}),_jsx(Accordion,{title:`Un cobro nunca se completa`,id:`un-cobro-nunca-se-completa`,children:_jsx(_components.p,{children:`El usuario no lo aprobó. Las confirmaciones caducan a los 10 minutos.`})}),_jsx(Accordion,{title:`No llega ningún webhook`,id:`no-llega-ningun-webhook`,children:_jsx(_components.p,{children:`Un proyecto necesita URL de callback y secreto de firma. Con solo uno de los dos no se entrega nada.`})}),_jsx(Accordion,{title:`Llegó menos Vito del que cobré`,id:`llego-menos-vito-del-que-cobre`,children:_jsx(_components.p,{children:`Es la comisión de liquidación. Usa importes de 5 Vito o menos para evitarla, o inclúyela en tu precio.`})}),_jsx(Accordion,{title:`402 VITO_INSUFFICIENT_OWNER_FUNDS`,id:`402-vito-insufficient-owner-funds`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`/v1/add`}),` se financia con tu propio saldo, no se crea de la nada. Recarga.`]})})]}),`\n`,_jsxs(CardGroup,{cols:2,children:[_jsx(Card,{title:`Vito`,icon:`coins`,href:`/es/members/vito`,children:_jsx(_components.p,{children:`Saldos, el PIN y las comisiones.`})}),_jsx(Card,{title:`Solicitudes de pago`,icon:`receipt`,href:`/es/account/payment-requests`,children:_jsx(_components.p,{children:`Lo que ve el usuario cuando le cobras.`})}),_jsx(Card,{title:`@vetox-bot/vito en npm`,icon:`npm`,href:`https://www.npmjs.com/package/@vetox-bot/vito`,children:_jsx(_components.p,{children:`El paquete oficial de Node.js: una instalación, integración completa.`})})]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"API de Vito y compras","sidebarTitle":"API de Vito","description":"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.","icon":"code","keywords":["api de vito","compras","solicitudes de pago","desarrollador","clave api","comercio"],"href":"/es/members/vito-api"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Obtener acceso","slug":"obtener-acceso","depth":2,"children":[{"title":"Scopes","slug":"scopes","depth":3,"children":[]}]},{"title":"Autenticación","slug":"autenticación","depth":2,"children":[{"title":"Claves, rotación y almacenamiento","slug":"claves-rotación-y-almacenamiento","depth":3,"children":[]}]},{"title":"SDK oficial de Node.js","slug":"sdk-oficial-de-node-js","depth":2,"children":[{"title":"Instalación","slug":"instalación","depth":3,"children":[]},{"title":"Inicialización","slug":"inicialización","depth":3,"children":[]},{"title":"Opciones del cliente","slug":"opciones-del-cliente","depth":4,"children":[]},{"title":"Métodos disponibles","slug":"métodos-disponibles","depth":3,"children":[]},{"title":"Ejemplos de uso","slug":"ejemplos-de-uso","depth":3,"children":[]},{"title":"Comprobar la clave al arrancar","slug":"comprobar-la-clave-al-arrancar","depth":4,"children":[]},{"title":"Leer un saldo","slug":"leer-un-saldo","depth":4,"children":[]},{"title":"Cobrar a un usuario (vender un artículo)","slug":"cobrar-a-un-usuario-vender-un-artículo","depth":4,"children":[]},{"title":"Abonar Vito a un usuario","slug":"abonar-vito-a-un-usuario","depth":4,"children":[]},{"title":"Recorrer las transacciones","slug":"recorrer-las-transacciones","depth":4,"children":[]},{"title":"Idempotencia y reintentos","slug":"idempotencia-y-reintentos","depth":3,"children":[]},{"title":"Verificar webhooks con el SDK","slug":"verificar-webhooks-con-el-sdk","depth":3,"children":[]},{"title":"Gestión de errores","slug":"gestión-de-errores","depth":3,"children":[]},{"title":"Cancelar una llamada","slug":"cancelar-una-llamada","depth":3,"children":[]}]},{"title":"Cobrar a un usuario","slug":"cobrar-a-un-usuario","depth":2,"children":[{"title":"Parámetros de la petición — /v1/deduct","slug":"parámetros-de-la-petición-—-/v1/deduct","depth":3,"children":[]}]},{"title":"Abonar Vito a un usuario","slug":"abonar-vito-a-un-usuario-2","depth":2,"children":[]},{"title":"Comisiones","slug":"comisiones","depth":2,"children":[]},{"title":"Webhooks","slug":"webhooks","depth":2,"children":[{"title":"Verificar la firma","slug":"verificar-la-firma","depth":3,"children":[]},{"title":"Eventos","slug":"eventos","depth":3,"children":[]}]},{"title":"Códigos de error","slug":"códigos-de-error","depth":2,"children":[]},{"title":"Límites de tasa","slug":"límites-de-tasa","depth":2,"children":[]},{"title":"Endpoints","slug":"endpoints","depth":2,"children":[]},{"title":"Límites","slug":"límites","depth":2,"children":[]},{"title":"Lista de comprobación de seguridad","slug":"lista-de-comprobación-de-seguridad","depth":2,"children":[]},{"title":"Resolución de problemas","slug":"resolución-de-problemas","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"vetox-ec2a2bcb","siteName":"Vetox","title":"API de Vito y compras - Vetox","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{"en":{"href":"/en/members/vito-api","matchLevel":1},"ar":{"href":"/ar/members/vito-api","matchLevel":1},"zh-CN":{"href":"/zh-CN/members/vito-api","matchLevel":1},"fr":{"href":"/fr/members/vito-api","matchLevel":1},"de":{"href":"/de/members/vito-api","matchLevel":1},"ja":{"href":"/ja/members/vito-api","matchLevel":1},"ru":{"href":"/ru/members/vito-api","matchLevel":1},"es":{"href":"/es/members/vito-api","matchLevel":0},"tr":{"href":"/tr/members/vito-api","matchLevel":1},"nl":{"href":"/nl/members/vito-api","matchLevel":1},"pt":{"href":"/pt/members/vito-api","matchLevel":1},"it":{"href":"/it/members/vito-api","matchLevel":1},"pl":{"href":"/pl/members/vito-api","matchLevel":1},"id":{"href":"/id/members/vito-api","matchLevel":1},"hi":{"href":"/hi/members/vito-api","matchLevel":1},"ko":{"href":"/ko/members/vito-api","matchLevel":1},"vi":{"href":"/vi/members/vito-api","matchLevel":1},"uk":{"href":"/uk/members/vito-api","matchLevel":1}}},"lastModified":"2026-09-09T05:22:47.403Z","originalFileLocation":"es/members/vito-api.mdx","locale":"es"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Vetox\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/svg+xml\" sizes=\"180x180\" href=\"https://vetox.io/logo.svg\">\u003clink data-mint-head rel=\"icon\" type=\"image/svg+xml\" sizes=\"32x32\" href=\"https://vetox.io/logo.svg\">\u003clink data-mint-head rel=\"icon\" type=\"image/svg+xml\" sizes=\"16x16\" href=\"https://vetox.io/logo.svg\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"https://vetox.io/logo.svg\">\u003cmeta data-mint-head property=\"og:title\" content=\"API de Vito y compras - Vetox\">\u003cmeta data-mint-head property=\"og:description\" content=\"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Vetox\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.vetox.io/es/members/vito-api\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://vetox.io/brand/vetox-header-04.png\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"API de Vito y compras - Vetox\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://vetox.io/brand/vetox-header-04.png\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/vetox-ec2a2bcb/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Vetox\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0086FF\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.vetox.io/es/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/es/members/vito-api.md\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"es\" href=\"https://docs.vetox.io/es/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"en\" href=\"https://docs.vetox.io/en/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"ar\" href=\"https://docs.vetox.io/ar/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"zh-CN\" href=\"https://docs.vetox.io/zh-CN/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"fr\" href=\"https://docs.vetox.io/fr/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"de\" href=\"https://docs.vetox.io/de/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"ja\" href=\"https://docs.vetox.io/ja/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"ru\" href=\"https://docs.vetox.io/ru/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"tr\" href=\"https://docs.vetox.io/tr/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"nl\" href=\"https://docs.vetox.io/nl/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"pt\" href=\"https://docs.vetox.io/pt/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"it\" href=\"https://docs.vetox.io/it/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"pl\" href=\"https://docs.vetox.io/pl/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"id\" href=\"https://docs.vetox.io/id/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"hi\" href=\"https://docs.vetox.io/hi/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"ko\" href=\"https://docs.vetox.io/ko/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"vi\" href=\"https://docs.vetox.io/vi/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"uk\" href=\"https://docs.vetox.io/uk/members/vito-api\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"x-default\" href=\"https://docs.vetox.io/en/members/vito-api\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.vetox.io/#organization\",\"name\":\"Vetox\",\"url\":\"https://docs.vetox.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://vetox.io/logo.svg\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.vetox.io#website\",\"name\":\"Vetox\",\"url\":\"https://docs.vetox.io\",\"publisher\":{\"@id\":\"https://docs.vetox.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.vetox.io/es/members/vito-api#webpage\",\"url\":\"https://docs.vetox.io/es/members/vito-api\",\"name\":\"API de Vito y compras\",\"description\":\"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.\",\"dateModified\":\"2026-09-09T05:22:47.403Z\",\"isPartOf\":{\"@id\":\"https://docs.vetox.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.vetox.io/es/members/vito-api#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.vetox.io/es/members/vito-api#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Vito\",\"item\":\"https://docs.vetox.io/es/members/vito\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"API de Vito y compras\",\"item\":\"https://docs.vetox.io/es/members/vito-api\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.vetox.io/es/members/vito-api#article\",\"headline\":\"API de Vito y compras\",\"name\":\"API de Vito y compras\",\"description\":\"Permite que aplicaciones aprobadas carguen sobre tu Vito con confirmación por PIN, y gestiona las solicitudes de pago desde tu página de Compras.\",\"url\":\"https://docs.vetox.io/es/members/vito-api\",\"mainEntityOfPage\":{\"@id\":\"https://docs.vetox.io/es/members/vito-api#webpage\"},\"image\":\"https://vetox.io/brand/vetox-header-04.png\",\"dateModified\":\"2026-09-09T05:22:47.403Z\",\"keywords\":\"api de vito, compras, solicitudes de pago, desarrollador, clave api, comercio\",\"publisher\":{\"@id\":\"https://docs.vetox.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.vetox.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Vetox\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Vetox","nav":{"global":null,"languages":[{"language":"en","pages":[{"title":"en","href":"/en/members/vito-api"}]},{"language":"ar","pages":[{"title":"ar","href":"/ar/members/vito-api"}]},{"language":"zh-CN","pages":[{"title":"zh-CN","href":"/zh-CN/members/vito-api"}]},{"language":"fr","pages":[{"title":"fr","href":"/fr/members/vito-api"}]},{"language":"de","pages":[{"title":"de","href":"/de/members/vito-api"}]},{"language":"ja","pages":[{"title":"ja","href":"/ja/members/vito-api"}]},{"language":"ru","pages":[{"title":"ru","href":"/ru/members/vito-api"}]},{"language":"es","tabs":[{"tab":"Documentación","pages":[{"title":"Documentación","href":"/es"}]},{"tab":"Panel del servidor","pages":[{"title":"Panel del servidor","href":"/es/server-management/overview"}]},{"tab":"Tu cuenta","groups":[{"group":"Principal","icon":"house","pages":[{"title":"Resumen","sidebarTitle":"Resumen","icon":"house","href":"/es/account/overview"},{"title":"Mi Battle Pass","sidebarTitle":"Mi Battle Pass","icon":"medal","href":"/es/account/my-battle-pass"},{"title":"Recompensa diaria","sidebarTitle":"Recompensa diaria","icon":"calendar-check","href":"/es/members/daily-reward"},{"title":"Perfil público","sidebarTitle":"Perfil público","icon":"id-card","href":"/es/members/profile"},{"title":"Página de Membresía","sidebarTitle":"Membresía","icon":"user","href":"/es/account/membership-page"},{"title":"Premium y Gestionar bots","sidebarTitle":"Gestionar bots","icon":"robot","href":"/es/account/manage-bots"},{"title":"Reputación","sidebarTitle":"Reputación","icon":"thumbs-up","href":"/es/members/reputation"},{"title":"Votación","sidebarTitle":"Votación","icon":"thumbs-up","href":"/es/members/voting"}]},{"group":"Utilidades","icon":"palette","pages":[{"title":"Personalización de perfil","sidebarTitle":"Personalización de perfil","icon":"image","href":"/es/members/profile-customization"},{"title":"Personalización de rango","sidebarTitle":"Personalización de rango","icon":"gauge","href":"/es/members/rank-customization"},{"title":"Personalización del nombre","sidebarTitle":"Personalización del nombre","icon":"font","href":"/es/members/name-customization"},{"title":"Insignias","sidebarTitle":"Insignias","icon":"certificate","href":"/es/members/badges"},{"title":"Mis copias de seguridad","icon":"box-archive","sidebarTitle":"Mis copias de seguridad","href":"/es/members/my-backups"}]},{"group":"Vito","icon":"coins","pages":[{"title":"Vito","sidebarTitle":"Vito","icon":"coins","href":"/es/members/vito"},{"title":"Transacciones de Vito","sidebarTitle":"Transacciones de Vito","icon":"receipt","href":"/es/account/vito-transactions"},{"title":"Solicitudes de pago","sidebarTitle":"Solicitudes de pago","description":"Revisa, aprueba o cancela cargos de Vito solicitados por aplicaciones conectadas, y la ventana de 10 minutos con la que operan.","icon":"file-invoice","href":"/es/account/payment-requests"},{"title":"API de Vito y compras","sidebarTitle":"API de Vito","icon":"code","href":"/es/members/vito-api"}]},{"group":"Clasificación","icon":"ranking-star","pages":[{"title":"Clasificaciones","sidebarTitle":"Clasificaciones","description":"Clasificaciones globales de Vito, XP y reputación: el top 100 de cada una, actualizado dos veces al día.","icon":"ranking-star","href":"/es/members/leaderboards"},{"title":"Usuarios más ricos","sidebarTitle":"Usuarios más ricos","icon":"coins","href":"/es/account/richest-users"},{"title":"Brokers de teclado","sidebarTitle":"Brokers de teclado","icon":"chart-line","href":"/es/account/keyboard-brokers"},{"title":"Más votados","sidebarTitle":"Más votados","icon":"thumbs-up","href":"/es/account/most-liked"}]}]},{"tab":"Comandos","pages":[{"title":"Comandos","href":"/es/commands/overview"}]},{"tab":"Ayuda","pages":[{"title":"Ayuda","href":"/es/help/faq"}]}]},{"language":"tr","pages":[{"title":"tr","href":"/tr/members/vito-api"}]},{"language":"nl","pages":[{"title":"nl","href":"/nl/members/vito-api"}]},{"language":"pt","pages":[{"title":"pt","href":"/pt/members/vito-api"}]},{"language":"it","pages":[{"title":"it","href":"/it/members/vito-api"}]},{"language":"pl","pages":[{"title":"pl","href":"/pl/members/vito-api"}]},{"language":"id","pages":[{"title":"id","href":"/id/members/vito-api"}]},{"language":"hi","pages":[{"title":"hi","href":"/hi/members/vito-api"}]},{"language":"ko","pages":[{"title":"ko","href":"/ko/members/vito-api"}]},{"language":"vi","pages":[{"title":"vi","href":"/vi/members/vito-api"}]},{"language":"uk","pages":[{"title":"uk","href":"/uk/members/vito-api"}]}]},"title":"API de Vito y compras - Vetox","buildId":"dpl_cadrRc5H9XQiJQbDFN5mcYRs2PAj","deploymentId":"dpl_cadrRc5H9XQiJQbDFN5mcYRs2PAj","dynamics":[],"chunks":[]}