Ir al contenido principal

API REST para pagos QR en Perú

API REST predecible, JSON puro, webhooks firmados. Integra con Checkout.js en minutos o usa la API directamente.

Checkout.js — La vía rápida

Tu backend crea el pago, tu frontend abre el modal. TAYPI se encarga del resto.

Tu backend (PHP)
// 1. Crea el pago con tu secret key
$response = Http::withHeaders([
  'Authorization' => 'Bearer ' . $publicKey,
  'Taypi-Signature' => $signature,
  'Taypi-Timestamp' => $timestamp,
  'Idempotency-Key' => $reference,
])->post('https://app.taypi.pe/api/v1/payments', [
  'amount' => 50.00,
  'reference' => 'ORD-12345',
]);

// 2. Devuelve solo el token al frontend
return [
  'checkout_token' => $response['data']['checkout_token']
];
Tu frontend (JS)
<script src="https://app.taypi.pe/checkout.js"></script>

<script>
  Taypi.publicKey = 'taypi_pk_live_xxx';

  // Abre el modal con el QR
  Taypi.open({
    sessionToken: checkout_token,
    onSuccess: (result) => {
      console.log('Pagado:', result.paid_at);
      window.location.href = '/gracias';
    },
    onExpired: () => { /* QR expiró */ },
    onClose: () => { /* Cerró modal */ },
  });
</script>
Checkout.js renderiza el modal y hace polling automático cada 3s
Tu secret key nunca toca el frontend

Autenticación

Cada request lleva Bearer token + firma HMAC-SHA256 + timestamp.

Header Requerido Descripción
Authorization Siempre Tu public key
Taypi-Timestamp Siempre Unix epoch en segundos
Taypi-Signature Siempre Firma HMAC-SHA256
Idempotency-Key Solo POST Previene duplicados (TTL 24h)
Content-Type POST/PUT
Fórmula de la firma HMAC-SHA256
Taypi-Signature = HMAC-SHA256(
  secret_key,
  timestamp + "\n" + METHOD + "\n" + path + "\n" + body
)

Public Key (frontend + headers)

taypi_pk_live_+ 32 chars hex

Secret Key (solo backend, firma HMAC)

taypi_sk_live_+ 64 chars hex

Endpoints

Base URL: https://app.taypi.pe

GET /api/v1/merchant Datos del comercio autenticado
POST /api/v1/payments Crear un pago con QR
GET /api/v1/payments Listar pagos con filtros y paginación
GET /api/v1/payments/{payment_id} Consultar estado de un pago
POST /api/v1/payments/{payment_id}/cancel Cancelar un pago pendiente
GET /v1/checkout/sessions/{token} Obtener datos de sesión (checkout.js)
GET /checkout/{token}/status Polling de estado (checkout.js)
GET /v1/health Estado del servicio

API Merchant

60 req/min

Checkout Sessions

30 req/min

Status Polling

120 req/min

Idempotencia

TTL 24h

Crear un pago

POST /api/v1/payments — el endpoint que más vas a usar.

Request
{
  "amount": 50.00,
  "reference": "ORD-12345",
  "description": "Compra en Mi Tienda",
  "metadata": {
    "source": "web"
  }
}

amount: S/ 1.00 — S/ 50,000.00 · reference: único por comercio

201 Created
{
  "data": {
    "payment_id": "019...",
    "amount": "50.00",
    "currency": "PEN",
    "status": "pending",
    "checkout_token": "019...",
    "expires_at": "2026-03-28T11:15:00-05:00"
  },
  "message": "Pago creado exitosamente."
}

checkout_token: úsalo con Checkout.js · expira en 15 min

Webhooks firmados

Cada webhook lleva firma HMAC-SHA256 para que verifiques su autenticidad. 3 reintentos automáticos si falla.

Headers del webhook
Taypi-Signature: sha256=a1b2c3d4...
Taypi-Timestamp: 1709312400
Taypi-Webhook-Id: wh_019...
Payload: payment.completed
{
  "event": "payment.completed",
  "payment_id": "019...",
  "amount": "50.00",
  "currency": "PEN",
  "status": "completed",
  "reference": "ORD-12345",
  "paid_at": "2026-03-28T10:30:00-05:00"
}
payment.completed El cliente pagó exitosamente
payment.expired El QR expiró sin pago (15 min)
payment.cancelled El comercio canceló el pago
payment.failed Error del procesador

Ciclo de vida del pago

pending → QR generado, esperando pago (15 min)
completed → Pago recibido, webhook disparado
expired → QR expiró sin pago
cancelled → Cancelado por el comercio
failed → Error del procesador

Errores predecibles

HTTP codes estándar + mensajes en español. Sin sorpresas.

422 Validation Error
{
  "message": "Los datos no son válidos.",
  "errors": {
    "amount": ["El monto debe ser al menos 1."],
    "reference": ["La referencia es obligatoria."]
  }
}
429 Rate Limited
// Headers de rate limit en cada response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1709312460

// Body:
{
  "message": "Demasiadas solicitudes."
}

Empieza a integrar hoy

Crea tu cuenta, obtén tus API keys y prueba en sandbox. Tu primer pago en minutos.