API de Links de Pago

    Genera enlaces de pago dinámicamente desde tu backend.

    Crear Link de Pago

    Este endpoint te permite crear un enlace de pago configurado específicamente para una orden o cliente.

    POST /v1/paymentlink
    curl -X POST https://api.pabilo.app/v1/paymentlink \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer TU_API_KEY" \
      -d '{
        "amount": 50.00,
        "currency": "USD",
        "description": "Orden #1234 - Pack Premium",
        "notification_by_whastapp": false,
        "webhook_url": "https://tu-sitio.com/webhook/pabilo",
        "user_bank_id": "ID_DE_TU_CUENTA_BANCARIA",
        "client_id": "ID_DEL_CLIENTE",
        "items": [
          { "product_id": "6a7c...", "quantity": 1 },
          { "name": "Envío", "unit_price": 10, "quantity": 1 }
        ],
        "redirect_url": "https://tu-sitio.com/gracias",
        "expiration_time": 1440,
        "rate_expiration_time": 120
      }'

    Parámetros

    • items (opcional): Desglose de lo que se cobra. Si se envía este campo, el campo amount es ignorado y el total se calcula sumando el precio de cada ítem. Los ítems pueden referenciar tu catálogo (con product_id) o ser líneas ad-hoc (con name y unit_price).
    • client_id (opcional): ID del cliente al que va dirigido el cobro.
    • amount: Monto a cobrar. Se ignora si envías items.
    • currency (opcional): Moneda del monto: VEF (Bolívares, por defecto), USD, EUR o USDT. Para monedas distintas de VEF, el monto se convierte a Bolívares con la tasa vigente al momento de validar el pago.
    • webhook_url: URL donde enviaremos una notificación POST cuando el pago sea verificado.
    • redirect_url: URL a donde redirigiremos al usuario tras un pago exitoso.
    • user_bank_id: ID de la cuenta bancaria donde quieres recibir el dinero. Ver cómo copiarlo desde el Dashboard →
    • expiration_time (opcional): Tiempo de expiración del enlace en minutos desde su creación. Si no se envía o se envía vacío, el enlace expira en 24 horas (1440 minutos). Envía -1 para que el enlace nunca expire.
      Ejemplos: 2 → expira en 2 minutos · 60 → expira en 1 hora · 1440 → expira en 24 horas · -1 → sin expiración.
    • rate_expiration_time (opcional, solo monedas ≠ VEF): Minutos que la tasa de cambio queda congelada en el enlace. Por defecto 60 (1 hora). Mientras esté vigente, todos pagan con la misma tasa; al vencer se actualiza automáticamente. La respuesta incluye rate_exchange (tasa Bs por unidad), rate_updated_at y rate_expiration_time; la validez es rate_updated_at + rate_expiration_time.

    Respuesta

    json
    {
      "id": "pl_abc123...",
      "url": "https://pabilo.app/pay/pl_abc123...",
      "amount": 50.00,
      "status": "active",
      "client_id": "ID_DEL_CLIENTE",
      "items": [
        {
          "product_id": "6a7c...", "name": "Producto Premium",
          "quantity": 1, "unit_price": 40, "currency": "USD"
        },
        { "name": "Envío", "quantity": 1, "unit_price": 10, "currency": "USD" }
      ]
    }

    Obtener Link por ID

    GET /paymentlink/{id}
    curl -X GET https://api.pabilo.app/paymentlink/pl_abc123... \
      -H "Authorization: Bearer TU_API_KEY"

    Webhooks

    Cuando un pago es procesado, el sistema envía automáticamente una notificación POST al webhook_url configurado con información detallada de la transacción.

    Estructura del Webhook

    El webhook envía un objeto JSON con la siguiente estructura:

    json
    {
      "payment_link_id": "675725869e6febc736848bf1",
      "status": "paid",
      "credit_balance": 150.50,
      "payment_link": {
        "id": "675725869e6febc736848bf1",
        "created_at": "2026-02-12T18:00:00Z",
        "updated_at": "2026-02-12T18:05:30Z",
        "name": "Pago de Servicio",
        "amount": 100.00,
        "currency": "VEF",
        "description": "Pago mensual de hosting",
        "notification_by_whastapp": true,
        "webhook_url": "https://myapp.com/webhooks/payment",
        "webhook_method": "POST",
        "user_bank_id": "675725869e6febc736848bf2",
        "user_id": "675725869e6febc736848bf3",
        "status": "paid",
        "status_detail": "",
        "url": "https://pabilo.app/pay/675725869e6febc736848bf1",
        "redirect_url": "https://myapp.com/success",
        "with_subscription_id": null,
        "type": "api",
        "client_id": "675725869e6febc736848bf5",
        "items": [
          {
            "name": "Pago mensual de hosting",
            "quantity": 1,
            "unit_price": 100.00,
            "currency": "VEF"
          }
        ]
      },
      "user_bank_payment": {
        "id": "675725869e6febc736848bf4",
        "created_at": "2026-02-12T18:05:30Z",
        "updated_at": "2026-02-12T18:05:30Z",
        "bank_reference_id": "0025513902095",
        "user_id": "675725869e6febc736848bf3",
        "amount": 100.00,
        "user_bank_id": "675725869e6febc736848bf2",
        "status": "paid",
        "credit_cost": 2.0
      }
    }

    Campos Principales

    • payment_link_id: ID del link de pago
    • status: Estado del pago (paid, failed, pending, canceled, expired)
    • credit_balance: Balance de créditos actual del usuario
    • payment_link: Objeto completo del link de pago con todos sus detalles
    • user_bank_payment: Detalles de la transacción bancaria (null si el pago falló)

    Ejemplo de Pago Fallido

    json
    {
      "payment_link_id": "675725869e6febc736848bf1",
      "status": "failed",
      "credit_balance": 148.50,
      "payment_link": {
        "id": "675725869e6febc736848bf1",
        "status": "failed",
        "status_detail": "payment not found: bank API returned status 400",
        ...
      },
      "user_bank_payment": null
    }

    Mejores Prácticas

    • Idempotencia: Usa payment_link_id para evitar procesamiento duplicado
    • Validación: Siempre verifica el campo status antes de procesar
    • Verificación de Monto: Cruza el monto en user_bank_payment.amount con el monto esperado
    • Respuesta: Tu endpoint debe retornar un código HTTP 2xx para confirmar la recepción
    • Errores: Revisa payment_link.status_detail para detalles de pagos fallidos

    Mensajes de Error Comunes

    • "payment not found": Transacción no encontrada en el banco
    • "payment already exists": Referencia de pago duplicada
    • "bank not available": API del banco temporalmente no disponible
    • "payment amount not valid": El monto no coincide