SDK Oficial — TypeScript / JavaScript
Integra Pabilo en tu aplicación Node.js, Next.js o cualquier runtime moderno de JavaScript con el SDK oficial.
Zero dependencias
El SDK no tiene dependencias de runtime. Solo JavaScript puro.
TypeScript nativo
Tipos completos con discriminated unions para cada respuesta.
ESM + CommonJS
Salida dual compatible con todos los entornos modernos.
Instalación
npm install @pabilo/sdk
# o
pnpm add @pabilo/sdkConfiguración inicial
Crea una instancia de PabiloClient con tu API Key obtenida en la sección de API Keys.
import { PabiloClient } from '@pabilo/sdk';
const pabilo = new PabiloClient({ apiKey: 'YOUR_API_KEY' });El cliente expone cuatro namespaces:
| Namespace | Descripción |
|---|---|
| pabilo.me | Perfil del usuario y plan activo |
| pabilo.bankAccounts | Gestión de cuentas bancarias conectadas |
| pabilo.paymentLinks | Crear y consultar enlaces de pago |
| pabilo.payments | Verificar pagos por referencia bancaria |
pabilo.me
me.getMe()
Retorna el perfil del usuario autenticado.
const user = await pabilo.me.getMe();
console.log(user.id); // string
console.log(user.email); // string | undefined
console.log(user.fullName); // string | undefined
console.log(user.credits); // number | undefined
console.log(user.planIsActive); // boolean | undefinedme.getPlan()
Retorna el plan de suscripción activo.
const plan = await pabilo.me.getPlan();
console.log(plan.name); // e.g. 'Pro'
console.log(plan.planType); // 'credit' | 'unlimited' | 'counter'
console.log(plan.period); // 'month' | 'six_months' | 'year'
console.log(plan.requestLimit); // number (-1 = ilimitado)
console.log(plan.initialCredits); // numberpabilo.bankAccounts
bankAccounts.list()
Retorna todas las cuentas bancarias conectadas al usuario.
const banks = await pabilo.bankAccounts.list();
for (const bank of banks) {
console.log(bank.id); // MongoDB ObjectId
console.log(bank.provider); // 'VE_BAN' | 'VE_BAN_EMP_V2' | ...
console.log(bank.description); // nombre de la cuenta
}bankAccounts.create(req)
Conecta una cuenta bancaria. Cada proveedor tiene su propio tipo de request — TypeScript valida los campos requeridos por proveedor.
BDV personal — VE_BAN
const bank = await pabilo.bankAccounts.create({
bankProvider: 'VE_BAN',
description: 'Mi cuenta BDV personal',
userBankPhone: '04241234567',
userBankDni: '12345678',
username: 'usuario_portal_bdv',
password: 'contraseña_portal_bdv',
});BDV empresa — VE_BAN_EMP_V2
const bank = await pabilo.bankAccounts.create({
bankProvider: 'VE_BAN_EMP_V2',
description: 'Cuenta empresa BDV',
userBankPhone: '04241234567',
userBankDni: '12345678',
accountNumber: '01020000000000000000',
apiKey: 'bdv_api_key_here',
});Banco de pruebas — BANK_TEST
const bank = await pabilo.bankAccounts.create({ bankProvider: 'BANK_TEST' });bankAccounts.delete(id)
await pabilo.bankAccounts.delete(bank.id);pabilo.paymentLinks
paymentLinks.create(req)
Crea un enlace de pago que el cliente puede usar para pagar vía Pago Móvil.
const link = await pabilo.paymentLinks.create({
amount: 4000,
description: 'Orden #1234',
userBankId: bank.id,
// opcionales
name: 'Servicio mensual',
redirectUrl: 'https://miapp.com/gracias',
webhookUrl: 'https://miapp.com/webhook/pabilo',
notificationByWhatsapp: true,
currency: 'VEF', // VEF (por defecto), USD, EUR o USDT
});
console.log(link.url); // https://pabilo.app/pay/...
console.log(link.id);
console.log(link.status); // 'pending' | 'active' | 'paid' | 'failed' | ...paymentLinks.list(req?)
const page = await pabilo.paymentLinks.list({
limit: 10,
page: 1,
status: 'pending',
search: 'orden',
});
console.log(page.total);
console.log(page.items); // PaymentLink[]paymentLinks.getInfo(id)
const link = await pabilo.paymentLinks.getInfo('69d0083b691af50b78e07921');
console.log(link.status); // 'paid'
console.log(link.statusDetail); // razón del estado actualpaymentLinks.isPaid(id)
const paid = await pabilo.paymentLinks.isPaid(link.id);
if (paid) {
// procesar la orden
}paymentLinks.update(id, req)
const updated = await pabilo.paymentLinks.update(link.id, {
amount: 5000,
description: 'Orden actualizada',
});pabilo.payments
payments.verify(userBankId, req)
Verifica si una transferencia específica existe en una cuenta bancaria conectada. Retorna una discriminated union en el campo found.
const result = await pabilo.payments.verify(bank.id, {
amount: 4000,
bankReference: '12345678',
movementType: 'GENERIC', // 'GENERIC' | 'MOVIL_PAY' | 'TRANSFER' | 'C2P'
});
if (result.found) {
console.log(result.isNew); // true si es la primera verificación
console.log(result.data.credit_cost);
const payment = result.data.user_bank_payment;
if (payment) {
console.log(payment.amount);
console.log(payment.bank_reference_id);
console.log(payment.payment_params.fecha_pago);
console.log(payment.payment_params.banco_origen);
console.log(payment.payment_params.telefono_pagador);
}
} else {
// result.reason → 'BANK_NOT_AVAILABLE' | 'PAYMENT_NOT_FOUND' | 'SESSION_ALREADY_ACTIVE'
}HTTP 200 para "no encontrado"
BANK_NOT_AVAILABLE y PAYMENT_NOT_FOUND. El SDK maneja esto de forma transparente — estos casos nunca se lanzan como errores.| movementType | Descripción |
|---|---|
| GENERIC | Cualquier tipo de movimiento (por defecto) |
| MOVIL_PAY | Pago Móvil |
| TRANSFER | Transferencia bancaria |
| C2P | Cuenta a Persona |
Webhooks
Cuando un enlace de pago es pagado, la API envía un POST al webhookUrl. Importa PaymentLinkWebhookPayload para tipar tu handler.
import type { PaymentLinkWebhookPayload } from '@pabilo/sdk';
// Next.js App Router
export async function POST(req: Request) {
const payload: PaymentLinkWebhookPayload = await req.json();
console.log(payload.payment_link_id);
console.log(payload.status); // 'paid'
console.log(payload.credit_balance);
const payment = payload.user_bank_payment;
if (payment) {
console.log(payment.amount);
console.log(payment.bank_reference_id);
console.log(payment.payment_params.fecha_pago);
}
return Response.json({ ok: true });
}Manejo de errores
Todos los métodos lanzan PabiloError en caso de errores de API o de red.
import { PabiloClient, PabiloError } from '@pabilo/sdk';
try {
const link = await pabilo.paymentLinks.create({ ... });
} catch (err) {
if (err instanceof PabiloError) {
console.error(err.code); // PabiloErrorCode string
console.error(err.message); // mensaje legible de la API
console.error(err.statusCode); // código HTTP
console.error(err.raw); // respuesta cruda de la API
}
}| Código | Descripción |
|---|---|
| BAD_REQUEST | Cuerpo o parámetros inválidos |
| UNAUTHORIZED | API key faltante o inválida |
| FORBIDDEN | Acción no permitida |
| NOT_FOUND | Recurso no encontrado |
| USER_BANK_ALREADY_EXISTS | La cuenta bancaria ya está conectada |
| USER_BANCK_BAD_PASSWORD | Credenciales del portal bancario incorrectas |
| USER_BANCK_PASSWORD_EXPIRED | Contraseña del portal bancario expirada |
| USER_BANCK_BLOCKED | Usuario del portal bancario bloqueado |
| USER_BANCK_BAD_API_KEY | API Key o Secret del banco inválidos |
| NOT_ENOUGH_CREDITS | Créditos insuficientes |
| PLAN_IS_NOT_ACTIVE | El plan de la cuenta está inactivo |
| REQUEST_LIMIT_REACHED | Límite de requests del plan alcanzado |
| BANK_ACCOUNT_LIMIT_REACHED | Límite de cuentas bancarias del plan alcanzado |
| BANK_NOT_AVAILABLE | Banco temporalmente fuera de línea |
| SESSION_ALREADY_ACTIVE | Usuario tiene una session activa en el banco por favor cierre para continuar |
| BANK_TOO_MANY_REQUESTS | Rate limit del banco |
| PAYMENT_NOT_FOUND | Referencia de transferencia no encontrada |
| PAYMENT_ALREADY_EXISTS | Transferencia ya verificada anteriormente |
| INTERNAL_ERROR | Error interno del servidor API |
| NETWORK_ERROR | Request no pudo llegar a la API |
Pruebas con BANK_TEST
Usa BANK_TEST para probar el flujo completo sin conectar un banco real. La referencia 67890 siempre devuelve un pago encontrado.
// 1. Crear banco de prueba
const bank = await pabilo.bankAccounts.create({ bankProvider: 'BANK_TEST' });
// 2. Crear enlace de pago
const link = await pabilo.paymentLinks.create({
amount: 100,
description: 'Test payment',
userBankId: bank.id,
webhookUrl: 'https://miapp.com/webhook',
});
// 3. Verificar con referencia de prueba
const result = await pabilo.payments.verify(bank.id, {
amount: 0,
bankReference: '67890',
});
// result.found === true
// 4. Limpiar
await pabilo.bankAccounts.delete(bank.id);Ejemplo: Next.js
lib/pabilo.ts
import { PabiloClient } from '@pabilo/sdk';
export const pabilo = new PabiloClient({
apiKey: process.env.PABILO_API_KEY!,
});app/api/checkout/route.ts
import { pabilo } from '@/lib/pabilo';
import { PabiloError } from '@pabilo/sdk';
export async function POST(req: Request) {
const { bankId, amount } = await req.json();
try {
const link = await pabilo.paymentLinks.create({
amount,
description: 'Checkout',
userBankId: bankId,
redirectUrl: `${process.env.NEXT_PUBLIC_URL}/gracias`,
webhookUrl: `${process.env.NEXT_PUBLIC_URL}/api/webhook/pabilo`,
});
return Response.json({ url: link.url, id: link.id });
} catch (err) {
if (err instanceof PabiloError) {
return Response.json({ error: err.message }, { status: 400 });
}
throw err;
}
}app/api/webhook/pabilo/route.ts
import type { PaymentLinkWebhookPayload } from '@pabilo/sdk';
export async function POST(req: Request) {
const payload: PaymentLinkWebhookPayload = await req.json();
if (payload.status === 'paid') {
// procesar la orden ligada a payload.payment_link_id
}
return Response.json({ ok: true });
}Avanzado: HTTP client personalizado
import { PabiloClient, FetchHttpClient, type RequestOptions } from '@pabilo/sdk';
class LoggingHttpClient extends FetchHttpClient {
async request<T>(opts: RequestOptions): Promise<T> {
console.log('[pabilo]', opts.method, opts.path);
return super.request<T>(opts);
}
}
const pabilo = new PabiloClient({
apiKey: 'YOUR_API_KEY',
httpClient: new LoggingHttpClient(),
});
// URL base personalizada (staging, etc.)
const pabiloStaging = new PabiloClient({
apiKey: 'YOUR_API_KEY',
baseUrl: 'https://staging.api.pabilo.app',
});