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/sdk

    Configuració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:

    NamespaceDescripción
    pabilo.mePerfil del usuario y plan activo
    pabilo.bankAccountsGestión de cuentas bancarias conectadas
    pabilo.paymentLinksCrear y consultar enlaces de pago
    pabilo.paymentsVerificar 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 | undefined

    me.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);   // number

    pabilo.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 actual

    paymentLinks.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'
    }
    movementTypeDescripción
    GENERICCualquier tipo de movimiento (por defecto)
    MOVIL_PAYPago Móvil
    TRANSFERTransferencia bancaria
    C2PCuenta 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ódigoDescripción
    BAD_REQUESTCuerpo o parámetros inválidos
    UNAUTHORIZEDAPI key faltante o inválida
    FORBIDDENAcción no permitida
    NOT_FOUNDRecurso no encontrado
    USER_BANK_ALREADY_EXISTSLa cuenta bancaria ya está conectada
    USER_BANCK_BAD_PASSWORDCredenciales del portal bancario incorrectas
    USER_BANCK_PASSWORD_EXPIREDContraseña del portal bancario expirada
    USER_BANCK_BLOCKEDUsuario del portal bancario bloqueado
    USER_BANCK_BAD_API_KEYAPI Key o Secret del banco inválidos
    NOT_ENOUGH_CREDITSCréditos insuficientes
    PLAN_IS_NOT_ACTIVEEl plan de la cuenta está inactivo
    REQUEST_LIMIT_REACHEDLímite de requests del plan alcanzado
    BANK_ACCOUNT_LIMIT_REACHEDLímite de cuentas bancarias del plan alcanzado
    BANK_NOT_AVAILABLEBanco temporalmente fuera de línea
    SESSION_ALREADY_ACTIVEUsuario tiene una session activa en el banco por favor cierre para continuar
    BANK_TOO_MANY_REQUESTSRate limit del banco
    PAYMENT_NOT_FOUNDReferencia de transferencia no encontrada
    PAYMENT_ALREADY_EXISTSTransferencia ya verificada anteriormente
    INTERNAL_ERRORError interno del servidor API
    NETWORK_ERRORRequest 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',
    });