Links de pago y widget de transferencia
Tres formas de mostrarle al comprador adónde transferir, de menos a más código. Las tres crean pagos de Talo comunes: mismos estados, mismos eventos, mismo webhook.
| Querés | Usá | Tu código |
|---|---|---|
| Mandar al comprador a pagar un pedido | La página de pago de Talo (payment_url): monto, alias y CVU con botones para copiar, cuenta regresiva, titular y CUIT | Creás el pago en tu servidor y redirigís a payment_url |
| Vender sin checkout: por chat, en tu bio o con un QR en el mostrador | Un link de pago (/l/<id>) | Ninguno: creás el link una vez |
| Que el comprador no salga de tu sitio | El widget <talo-checkout>, o su versión React del registry de shadcn | Creás el pago en tu servidor y mostrás el widget con su id y su checkout_token |
payment.paid, y antes releé el pago). Los links y el widget son solo pantalla: cualquiera puede disparar un evento en el navegador o volver a tu sitio desde la página de Talo. Ver Webhooks.Links de pago
Un link reutilizable para un producto o un monto: lo compartís por WhatsApp, lo pegás en tu bio o imprimís su QR. Cada comprador que toca Pagar por transferencia recibe un pago nuevo, con su propio CVU, y va a la página de Talo a pagarlo. Los links de Talo son en cripto o BRL y vencen a los 15 minutos; estos son en pesos, por transferencia, y duran hasta que los desactivás.
npx talo-hub links create --title "Clase de yoga" --amount 15000
# o con monto a elección: --min 1000 --max 50000También desde el dashboard, en Links de pago. Hace falta una key charge o full. La respuesta:
{
"id": "Ab3dE6gH9jKq",
"url": "https://talopartnerhub.vercel.app/l/Ab3dE6gH9jKq",
"qr_url": "https://talopartnerhub.vercel.app/l/Ab3dE6gH9jKq/qr.svg",
"environment": "sandbox",
"title": "Clase de yoga",
"description": null,
"amount": 15000,
"min_amount": null,
"max_amount": null,
"redirect_url": null,
"active": true,
"created_at": "2026-10-29T15:00:00.000Z"
}title: de 1 a 80 caracteres. Lo ve el comprador y queda comomotivede cada pago.description: hasta 280.- El monto:
amount(precio fijo) omin_amountymax_amount(el comprador escribe cuánto, dentro del rango). Positivos, con hasta 2 decimales y hasta $100.000.000. redirect_url(opcional): URL https adonde la página de Talo devuelve al comprador (http solo para localhost).qr_url: el QR del link en SVG, listo para imprimir.
Qué ve el comprador
El título, la descripción y el monto (o un campo para escribirlo, con el rango), un aviso si el link es de sandbox y el botón Pagar por transferencia. Al tocarlo, el hub crea el pago y lo manda a la página de Talo, donde ve el CVU y el alias. Si vuelve a tocarlo desde el mismo navegador durante el día, mientras ese pago siga pendiente (o le falte plata, si transfirió de menos) por el mismo monto, recibe el mismo pago en vez de un CVU nuevo.
Para que nadie genere pagos en masa con un link público, el hub permite hasta 20 pagos por hora desde una misma red (IP) por link, y un freno de 200 por link cada 10 minutos; quien vuelve al link recupera el pago que ya había empezado (también si transfirió de menos), y eso no cuenta. Los que comparten red (el mismo Wi-Fi, una oficina) cuentan juntos. Pasado un límite, la página le pide al comprador que pruebe de nuevo más tarde. La red se distingue con un hash con clave del link y la IP, que se guarda un día y solo para estos límites: la IP no se guarda.
Entregar lo que vendiste
Los pagos de un link mandan los mismos eventos que cualquier pago. En payment.paid, el external_id del pago es link_<id del link>_<al azar> y el motive es el título del link. El id de un link tiene 12 letras y números, así que external_id.slice(5, 17) es siempre el id del link, traiga lo que traiga la parte al azar. Los pagos de un link también se ven con npx talo-hub links get <id> o GET /api/v1/payment-links/{id}.
Desactivar
npx talo-hub links disable <id>, el dashboard o DELETE /api/v1/payment-links/{id}. Es para siempre: para volver a vender, creá otro link. Los pagos que ya empezaron con él se pueden seguir pagando. Un link desactivado, o de una cuenta que desconectaste del hub, le muestra al comprador “Este link de pago no está disponible”, sin más detalles. Desconectar la cuenta desactiva todos sus links.
Widget de transferencia
Para que el comprador pague sin salir de tu página: tu servidor crea el pago (POST /api/v1/payments, con el monto que decide tu servidor) y a la página le pasa solo el id y el checkout_token de la respuesta. Con un script y una etiqueta:
<script src="https://talopartnerhub.vercel.app/widget/v1/talo-checkout.js" defer></script>
<talo-checkout payment-id="PAR-…" token="ct_…"></talo-checkout>Muestra el monto, el alias y el CVU con botones para copiar y el vencimiento, y sigue el estado en vivo: esperando la transferencia, lo que falta si pagaron de menos (UNDERPAID), pago recibido (SUCCESS u OVERPAID) o vencido (EXPIRED). En sandbox muestra un aviso de que no se mueve plata real, y siempre un link a la página de Talo. Los textos están en castellano.
- Atributos:
payment-idytoken(obligatorios), yhub(opcional: la URL del hub; por defecto, el origen desde el que se cargó el script). Si cambian, vuelve a empezar. - Consulta cada 4 segundos, espera hasta 30 si hay errores, se pausa con la pestaña oculta y para cuando el pago queda SUCCESS, OVERPAID o EXPIRED, si no lo encuentra, o 15 minutos después del vencimiento.
- Eventos (burbujean y salen del Shadow DOM):
talo-status(endetail, la vista pública del pago cada vez que cambia el estado o lo pagado),talo-paid,talo-expiredytalo-error. La propiedadpaymenttiene la última vista.
const checkout = document.querySelector("talo-checkout");
checkout.addEventListener("talo-paid", () => {
// Solo para la pantalla: el pedido se entrega en tu webhook firmado.
document.querySelector("#gracias").hidden = false;
});
checkout.addEventListener("talo-expired", () => {
document.querySelector("#nuevo-pago").hidden = false;
});Se adapta a tu diseño con variables CSS: --talo-accent, --talo-text, --talo-muted, --talo-bg, --talo-border, --talo-radius y --talo-font.
talo-checkout {
--talo-accent: #6d28d9;
--talo-radius: 4px;
--talo-font: "Inter", sans-serif;
}Si tu sitio manda una Content-Security-Policy, sumá el hub a script-src (el script) y a connect-src (sus consultas), o el hub que hayas puesto. style-src no cambia: el widget se estila con una hoja de estilos construida, no con estilos inline. En navegadores que no la tienen (Safari anterior a 16.4) usa un <style>, que un style-src estricto bloquea: ahí el widget funciona igual, sin estilos.
Content-Security-Policy: script-src 'self' https://talopartnerhub.vercel.app; connect-src 'self' https://talopartnerhub.vercel.appReact y Next.js (shadcn)
El mismo widget como componente React con Tailwind, desde el registry de shadcn: <TaloPaymentStatus paymentId token />, con hubUrl, onPaid, onExpired y className opcionales.
npx shadcn@latest add https://talopartnerhub.vercel.app/r/talo-payment-status.jsonPara Next.js (App Router) hay un bloque completo: el componente, lib/talo-hub.ts (solo servidor: createTaloPayment, getTaloPayment y verifyTaloWebhook), la ruta del webhook firmado (app/api/webhooks/talo/route.ts) y lib/talo-events.ts, donde escribís markOrderPaid. Usa TALO_HUB_API_KEY y TALO_HUB_WEBHOOK_SECRET.
npx shadcn@latest add https://talopartnerhub.vercel.app/r/talo-checkout-nextjs.json// app/checkout/actions.ts: el monto lo decide tu servidor, nunca el navegador
"use server";
import { redirect } from "next/navigation";
import { createTaloPayment } from "@/lib/talo-hub";
export async function pagar(orderId: string) {
const order = await db.orders.find(orderId);
const payment = await createTaloPayment({ amount: order.total, externalId: order.id, motive: `Pedido #${order.number}` });
await db.orders.update(order.id, { paymentId: payment.id });
redirect(`/pedido/${order.id}`);
}
// app/pedido/[id]/page.tsx: al navegador van solo el id y el checkout_token
const payment = await getTaloPayment(order.paymentId);
return <TaloPaymentStatus paymentId={payment.id} token={payment.checkout_token} />;El checkout token
checkout_token viene en la respuesta de POST /api/v1/payments y GET /api/v1/payments/{id} (y de las herramientas MCP create_payment y get_payment), no en las listas ni en los eventos del webhook. Es lo único que necesita el widget, y a diferencia de tu API key puede ir al navegador:
- Es de solo lectura y sirve para un único pago: no abre otros pagos, no cambia nada y no muestra datos de tu cuenta.
- Vence a los 15 días de emitido; cada lectura del pago trae uno nuevo (un pago de Talo dura como mucho 14 días).
- No se revoca de a uno: desconectar la cuenta los frena a todos.
Con él, cualquier página (de cualquier origen, sin key) lee la vista pública del pago en GET /api/public/payments/{id}?token=ct_…:
{
"id": "PAR-…",
"status": "PENDING",
"amount": 15000,
"currency": "ARS",
"paid": 0,
"cvu": "0000…",
"alias": "…",
"expires_at": "2026-10-30T15:00:00.000Z",
"motive": "Pedido #1001",
"payment_url": "https://…",
"environment": "sandbox"
}Todos los campos vienen siempre (en null si Talo no tiene el dato). Un token inválido, vencido o de otro pago, una cuenta desconectada y un pago que no existe responden igual: 404 not_found. El CDN guarda cada respuesta 3 segundos, así muchas pestañas abiertas cuestan una sola consulta. Más en Seguridad.