vecchiopay

Documentación

Con la API de VecchioPay cada venta recibe su propio CVU. Tu cliente transfiere, nosotros detectamos el depósito y te avisamos por webhook. Integrarlo lleva una tarde.

Inicio rápido

  1. Creá tu cuenta: arrancás en modo prueba, sin esperar ninguna aprobación.
  2. En el panel, Desarrolladores → creá una API key sk_test_… y un endpoint de webhook.
  3. Creá un pago y mandá a tu cliente al checkout_url.
  4. Cuando llegue payment.paid a tu webhook, marcá el pedido como pagado.
  5. Probalo todo con el Simulador del panel. Cuando se apruebe tu alta, cambiá a una clave sk_live_….
bash
curl -X POST https://api.tudominio.com/v1/payments \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: orden-1234" \
  -d '{
    "amount": 15999.90,
    "external_id": "orden-1234",
    "title": "Pedido #1234",
    "expires_in": "1h",
    "success_url": "https://mitienda.com/gracias",
    "cancel_url": "https://mitienda.com/carrito"
  }'
json
{
  "id": "pay_k3j9x0aa71m2...",
  "object": "payment",
  "livemode": false,
  "status": "NOT_PAID",
  "amount": 15999.9,
  "amount_paid": 0,
  "currency": "ARS",
  "external_id": "orden-1234",
  "cvu": "0000017012345678901234",
  "alias": "vecchio.k3j9x0aa",
  "checkout_url": "https://tudominio.com/pagar/pay_k3j9x0aa71m2...",
  "expires_at": "2026-10-04T15:30:00.000Z",
  "deposits": [],
  "refunds": []
}

Autenticación y modos

Mandá tu API key en cada request: Authorization: Bearer sk_test_…. Las claves se crean en el panel y se muestran una sola vez.

  • sk_test_… → modo prueba: todo simulado, ideal para desarrollar. En el checkout aparece un botón para simular la transferencia.
  • sk_live_… → modo real: CVUs reales y plata real. Requiere el alta aprobada.

Cada objeto trae livemode para que sepas de qué modo vino. Los webhooks de cada modo se firman con un secreto distinto.

Pagos y checkout

Un pago es un cobro con su propio CVU y alias. Estados: NOT_PAID → PARTIAL (pagaron menos) → PAID; o EXPIRED / CANCELED.

  • expires_in: de 30m a 30d (por defecto 24h). Al vencer, el CVU deja de recibir.
  • metadata: hasta 50 pares clave/valor (strings) que te devolvemos en cada webhook.
  • webhook_url: además de tus endpoints, mandamos los eventos de ese pago a esa URL.
  • Si te transfieren de más, el pago queda PAID con amount_paid mayor: podés devolver la diferencia.

Endpoints: POST /v1/payments, GET /v1/payments, GET /v1/payments/:id, POST /v1/payments/:id/cancel, POST /v1/payments/:id/refunds, GET /v1/payments/:id/refunds.

bash
# Devolver todo el depósito (o parte, con "amount")
curl -X POST https://api.tudominio.com/v1/payments/pay_.../refunds \
  -H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" \
  -d '{ "amount": 5000 }'

Webhooks

Configurá tus endpoints en el panel o por API (/v1/webhook_endpoints). Cada notificación es un POST JSON:

json
{
  "id": "6ac1...",
  "evento": "payment.paid",
  "modo": "live",
  "livemode": true,
  "creado": "2026-10-03T22:10:41.120Z",
  "data": { "id": "pay_...", "object": "payment", "status": "PAID", ... }
}
payment.paidEl pago se completó (lo que entró ≥ el monto).
payment.partially_paidEntró una transferencia por menos del total.
payment.expiredVenció sin completarse; el CVU deja de recibir.
payment.canceledLo cancelaste antes de que entrara plata.
payment.refundedDevolviste (total o parcialmente) una transferencia.
customer.deposit_receivedUn cliente transfirió a su CVU fijo.
customer.created / customer.updatedAlta, cambios, baja o reactivación de un cliente.
deposit.receivedEntró una transferencia a tu CVU principal.
withdrawal.created / withdrawal.confirmedRetiros a tu cuenta bancaria.
account.approvedSe aprobó el alta de tu cuenta.

Verificá la firma de cada webhook con el secreto de tu modo (panel → Desarrolladores):

node.js
import crypto from 'node:crypto';

// headers: x-webhook-timestamp, x-webhook-signature ("v1=<hex>")
// rawBody: el body EXACTO que llegó, sin re-serializar
export function verificar(headers, rawBody, secreto) {
  const ts = headers['x-webhook-timestamp'];
  const firma = headers['x-webhook-signature'] ?? '';
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // reenvíos viejos
  const esperada = 'v1=' + crypto.createHmac('sha256', secreto)
    .update(`${ts}.${rawBody}`).digest('hex');
  return firma.length === esperada.length &&
    crypto.timingSafeEqual(Buffer.from(firma), Buffer.from(esperada));
}
php
$ts = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$firma = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$esperada = 'v1=' . hash_hmac('sha256', $ts . '.' . $body, $secreto);
$valida = abs(time() - (int) $ts) < 300 && hash_equals($esperada, $firma);

Respondé 2xx en menos de 10 segundos. Si no, reintentamos a 1 min, 5 min, 30 min, 2 h, 6 h y 12 h. Un mismo evento puede llegar más de una vez: usá el id para no procesarlo dos veces.

Clientes con CVU fijo

Para clientes que te pagan seguido (cuotas, alquileres, abonos, mayoristas) creá un cliente: recibe un CVU propio y fijo. Todo lo que transfiera queda asociado a él, sin crear cobros, y te llega customer.deposit_received.

bash
curl -X POST https://api.tudominio.com/v1/customers \
  -H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" \
  -d '{ "name": "Juan Pérez", "tax_id": "20123456789", "external_id": "cli-42" }'

Con PATCH /v1/customers/:id cambiás el alias o das de baja el CVU ("active": false); la baja es reversible y el número no cambia.

Idempotencia

Mandá Idempotency-Key en los POST. Si reintentás con la misma clave (por un timeout, por ejemplo) te devolvemos la misma respuesta y no se crea un segundo pago. La clave vale 24 h; usarla con otro body devuelve 422. Las respuestas repetidas traen el header idempotent-replayed: true.

Errores y límites

Los errores responden { "statusCode": 422, "error": "INSUFFICIENT_FUNDS", "message": "No tenés saldo suficiente…" }.

  • 400 datos inválidos · 401 API key inválida · 403 sin permiso o cuenta suspendida · 404 no existe
  • 409 conflicto (ej. external_id repetido, cuenta sin activar) · 422 la operación no se pudo hacer (ej. saldo insuficiente)
  • 429 superaste el límite de requests por minuto: esperá y reintentá · 502 problema con el procesador

WooCommerce

Instalá el plugin, pegá tu API key y listo: al pagar, el cliente va al checkout de VecchioPay y el pedido se marca como pagado solo cuando llega la transferencia. El plugin registra su propio webhook, soporta devoluciones desde el pedido y el checkout por bloques.

  1. Subí el .zip en Plugins → Añadir nuevo → Subir plugin.
  2. WooCommerce → Ajustes → Pagos → VecchioPay: pegá la API key de prueba y la real, y el secreto de firma de cada modo.
  3. Tocá "Registrar webhook" y probá una compra en modo prueba.

Referencia completa

Todos los endpoints, campos y ejemplos están en la referencia interactiva (Swagger).