PagRealAPI v1 · DOCUMENTACIÓN
Visión generalPagReal.com
Base pública: https://api.pagreal.com/v1Guía oficial para cuentas Site y Mixto. Versión documentada: PagReal v8.3.0.

PAGREAL · API DE INTEGRACIÓN v1

Guía pública de integración para cuentas Site y Mixto.

Versión documentada: PagReal v8.3.0

Base pública: https://api.pagreal.com/v1

Esta documentación explica cómo autenticar una integración, consultar el estado de la cuenta, validar credenciales, leer la configuración de cobro y verificar pagos. También explica cómo funciona la cuota diaria de verificaciones del plan.

1. Antes de comenzar #

Necesitas un token activo generado desde la sección API de PagReal.

Todas las peticiones deben enviarse por HTTPS. No necesitas enviar user_id: el token identifica automáticamente a la cuenta propietaria de la consulta.

Los tokens de integración usan exclusivamente el prefijo prt_.

Header recomendado #

Authorization: Bearer prt_TU_TOKEN_SECRETO

En solicitudes POST agrega además:

Content-Type: application/json

También se admite el header alternativo de PagReal:

X-PagReal-Token: prt_TU_TOKEN_SECRETO

Buenas prácticas con el token #

2. Respuestas comunes #

Token no enviado · HTTP 401 #

{
  "ok": false,
  "code": "TOKEN_REQUIRED",
  "message": "Token de integración requerido."
}

Token inválido o revocado · HTTP 401 #

{
  "ok": false,
  "code": "TOKEN_INVALID",
  "message": "Token de integración inválido o revocado."
}

Cuenta inactiva · HTTP 403 #

{
  "ok": false,
  "code": "ACCOUNT_INACTIVE",
  "message": "La cuenta asociada al token está inactiva."
}

Límite técnico de frecuencia · HTTP 429 #

{
  "ok": false,
  "code": "RATE_LIMITED",
  "message": "Demasiadas solicitudes. Intenta nuevamente en unos segundos.",
  "retryAfter": 12
}

RATE_LIMITED es una protección técnica temporal. Es independiente de la cuota comercial diaria de tu plan.

3. GET /account #

Devuelve los datos básicos de la cuenta asociada al token y el estado de su plan.

Solicitud #

curl \
  -H "Authorization: Bearer prt_TU_TOKEN_SECRETO" \
  https://api.pagreal.com/v1/account

Respuesta · HTTP 200 #

{
  "ok": true,
  "accountType": "user",
  "user": {
    "id": "e7815f58-8457-11f1-ba19-020000cfa43c",
    "username": "mi_integrador",
    "name": "Mi negocio",
    "role": "site"
  },
  "access": {
    "subscriptionRequired": true,
    "active": true,
    "status": "active",
    "daysRemaining": 18,
    "expiresAt": "2026-09-21T23:59:59.000Z",
    "nextPaymentDate": "21/09/2026",
    "planName": "Básico"
  },
  "passwordSecurity": {
    "algorithm": "scrypt",
    "hashExposed": false,
    "verifyEndpoint": "/v1/auth/verify"
  }
}

Qué debes usar #

4. POST /auth/verify #

Permite validar el usuario y contraseña de la misma cuenta identificada por el token.

No se puede utilizar el token de una cuenta para validar la contraseña de otra.

Solicitud #

curl -X POST \
  https://api.pagreal.com/v1/auth/verify \
  -H "Authorization: Bearer prt_TU_TOKEN_SECRETO" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "mi_integrador",
    "password": "CLAVE_ESCRITA_POR_EL_USUARIO"
  }'

Credenciales correctas y plan activo · HTTP 200 #

{
  "ok": true,
  "valid": true,
  "accountType": "user",
  "subscriptionRequired": true,
  "accessActive": true,
  "daysRemaining": 18
}

Credenciales correctas pero plan vencido · HTTP 200 #

{
  "ok": true,
  "valid": true,
  "accountType": "user",
  "subscriptionRequired": true,
  "accessActive": false,
  "daysRemaining": 0
}

Usuario o contraseña incorrectos · HTTP 200 #

{
  "ok": true,
  "valid": false,
  "accountType": "user",
  "subscriptionRequired": true,
  "accessActive": false,
  "daysRemaining": 0
}

5. GET /config #

Devuelve el estado del acceso, el estado del monitoreo bancario y los métodos de pago activos configurados por la cuenta.

Solicitud #

curl \
  -H "Authorization: Bearer prt_TU_TOKEN_SECRETO" \
  https://api.pagreal.com/v1/config

Respuesta con banco activo · HTTP 200 #

{
  "ok": true,
  "accountType": "user",
  "access": {
    "subscriptionRequired": true,
    "active": true,
    "daysRemaining": 18,
    "expiresAt": "2026-09-21T23:59:59.000Z"
  },
  "automaticPayment": {
    "active": true,
    "state": "active",
    "bankCode": "0102",
    "accountLast4": "1028",
    "lastSuccessAt": "2026-09-03T14:00:00.000Z",
    "errorCode": "",
    "error": ""
  },
  "paymentMethods": [
    {
      "type": "mobile_payment",
      "bankCode": "0102",
      "phone": "04141234567",
      "documentType": "Cédula",
      "documentNumber": "12345678"
    },
    {
      "type": "bank_transfer",
      "bankCode": "0102",
      "accountHolderName": "Nombre Titular",
      "documentType": "Cédula",
      "documentNumber": "12345678",
      "accountNumber": "01020000000000000000"
    }
  ]
}

Respuesta con monitoreo pausado · HTTP 200 #

{
  "ok": true,
  "accountType": "user",
  "access": {
    "subscriptionRequired": true,
    "active": true,
    "daysRemaining": 18,
    "expiresAt": "2026-09-21T23:59:59.000Z"
  },
  "automaticPayment": {
    "active": false,
    "state": "paused",
    "bankCode": "0102",
    "accountLast4": "1028",
    "lastSuccessAt": "2026-09-03T14:00:00.000Z",
    "errorCode": "",
    "error": ""
  },
  "paymentMethods": []
}

automaticPayment.active solo debe considerarse disponible cuando vale true. Entre los estados visibles pueden aparecer active, paused, error, disconnected o connecting.

6. POST /payments/verify #

Consulta un pago recibido usando referencia, monto, fecha y banco.

Body #

{
  "reference": "6439",
  "amount": "12,00",
  "date": "2026-09-03",
  "bankCode": "0102"
}

Campos #

Solicitud cURL #

curl -X POST \
  https://api.pagreal.com/v1/payments/verify \
  -H "Authorization: Bearer prt_TU_TOKEN_SECRETO" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "6439",
    "amount": "12,00",
    "date": "2026-09-03",
    "bankCode": "0102"
  }'

Pago encontrado por primera vez · HTTP 200 #

{
  "ok": true,
  "accountType": "user",
  "found": true,
  "alreadyConsulted": false,
  "status": "FOUND",
  "payment": {
    "id": "uuid-del-historial",
    "reference": "6439",
    "amount": 12,
    "bankCode": "0102",
    "date": "2026-09-03"
  },
  "usage": {
    "charged": true,
    "used": 7,
    "limit": 150,
    "remaining": 143
  }
}

Pago encontrado que ya se había consultado · HTTP 200 #

{
  "ok": true,
  "accountType": "user",
  "found": true,
  "alreadyConsulted": true,
  "status": "ALREADY_CONSULTED",
  "payment": {
    "id": "uuid-del-historial",
    "reference": "6439",
    "amount": 12,
    "bankCode": "0102",
    "date": "2026-09-03"
  },
  "usage": {
    "charged": false,
    "used": 7,
    "limit": 150,
    "remaining": 143
  }
}

Pago no encontrado · HTTP 200 #

{
  "ok": true,
  "accountType": "user",
  "found": false,
  "alreadyConsulted": false,
  "status": "NOT_FOUND",
  "payment": {
    "id": "uuid-del-historial",
    "reference": "7352",
    "amount": 864,
    "bankCode": "0102",
    "date": "2026-09-03"
  },
  "usage": {
    "charged": true,
    "used": 8,
    "limit": 150,
    "remaining": 142
  }
}

7. Cómo funciona la cuota diaria del plan #

La cuota comercial se aplica únicamente a POST /payments/verify para cuentas con plan API.

Una solicitud lógica se identifica por esta combinación:

Cuándo consume #

Cuando una combinación lógica nueva puede procesarse, consume una unidad de la cuota. Tanto un resultado FOUND como un resultado NOT_FOUND cuentan cuando la consulta fue procesada.

Cuándo NO vuelve a consumir #

Si repites exactamente la misma combinación lógica, la consulta puede volver a ejecutarse pero no consume otra unidad, incluso si se repite más tarde. En la respuesta verás:

{
  "usage": {
    "charged": false,
    "used": 7,
    "limit": 150,
    "remaining": 143
  }
}

Esto permite reconsultar el mismo pago sin castigar la cuota del plan.

Límite diario alcanzado · HTTP 429 #

Una combinación lógica nueva que exceda el límite diario responde:

{
  "ok": false,
  "code": "DAILY_VERIFICATION_LIMIT_REACHED",
  "status": "LIMIT_REACHED",
  "message": "Has alcanzado el límite diario de verificaciones de tu plan.",
  "limit": 150,
  "used": 150,
  "remaining": 0,
  "date": "2026-09-03"
}

Una consulta ya conocida puede seguir siendo reconocida como repetida porque no representa una nueva unidad lógica.

Diferencia entre cuota y rate limit #

8. Errores de /payments/verify #

Plan inactivo · HTTP 403 #

{
  "ok": false,
  "code": "SERVICE_INACTIVE",
  "status": "INACTIVE",
  "message": "Acceso expirado. Renueva tu plan para continuar.",
  "daysRemaining": 0
}

Banco automático no disponible · HTTP 409 #

{
  "ok": false,
  "code": "BANK_MONITOR_INACTIVE",
  "status": "UNAVAILABLE",
  "message": "El pago automático no está activo en este momento.",
  "bankState": "paused",
  "bankErrorCode": ""
}

Esta respuesta no consume una nueva solicitud lógica porque la verificación no pudo procesarse correctamente.

Referencia inválida · HTTP 400 #

{
  "ok": false,
  "code": "INVALID_REFERENCE",
  "message": "La referencia debe contener los últimos 4 dígitos."
}

Monto inválido · HTTP 400 #

{
  "ok": false,
  "code": "INVALID_AMOUNT",
  "message": "Monto inválido."
}

Fecha inválida · HTTP 400 #

{
  "ok": false,
  "code": "INVALID_DATE",
  "message": "Fecha inválida. Usa YYYY-MM-DD o DD-MM-YYYY."
}

Banco no soportado · HTTP 400 #

{
  "ok": false,
  "code": "BANK_NOT_SUPPORTED",
  "message": "Banco no disponible."
}

9. Ejemplo PHP completo #

<?php

$token = 'prt_TU_TOKEN_SECRETO';
$url = 'https://api.pagreal.com/v1/payments/verify';

$payload = [
    'reference' => '6439',
    'amount' => '12,00',
    'date' => '2026-09-03',
    'bankCode' => '0102',
];

$ch = curl_init($url);

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $token,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_TIMEOUT => 15,
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);

curl_close($ch);

if ($error) {
    die('Error de conexión: ' . $error);
}

$data = json_decode($response, true);

if ($httpCode === 429 && ($data['code'] ?? '') === 'DAILY_VERIFICATION_LIMIT_REACHED') {
    echo 'Cuota diaria agotada';
    exit;
}

switch ($data['status'] ?? $data['code'] ?? '') {
    case 'FOUND':
        echo 'Pago encontrado';
        break;

    case 'ALREADY_CONSULTED':
        echo 'Pago encontrado y ya consultado anteriormente';
        break;

    case 'NOT_FOUND':
        echo 'Pago no encontrado';
        break;

    case 'INACTIVE':
    case 'SERVICE_INACTIVE':
        echo 'Plan inactivo';
        break;

    case 'UNAVAILABLE':
    case 'BANK_MONITOR_INACTIVE':
        echo 'Banco automático no disponible';
        break;

    default:
        echo $data['message'] ?? $data['error'] ?? 'Respuesta inesperada';
}

10. Flujo recomendado para un sitio web #

  1. Guarda el token únicamente en el backend de tu sitio.
  2. Usa GET /account al iniciar para conocer la cuenta y el estado del plan.
  3. Usa GET /config para saber si el cobro automático está disponible y mostrar los métodos de pago activos.
  4. Si necesitas validar las credenciales del mismo titular, usa POST /auth/verify.
  5. Cuando el cliente informe un pago, envía referencia, monto, fecha y banco a POST /payments/verify.
  6. Maneja FOUND, ALREADY_CONSULTED y NOT_FOUND como resultados normales de negocio.
  7. Maneja DAILY_VERIFICATION_LIMIT_REACHED, RATE_LIMITED, SERVICE_INACTIVE y BANK_MONITOR_INACTIVE como estados que requieren una acción diferente.
  8. Lee el objeto usage de cada verificación para conocer si esa consulta consumió cuota y cuántas quedan.

11. Resumen de endpoints #

GET /account #

POST /auth/verify #

GET /config #

POST /payments/verify #

12. Checklist de integración #


PagReal · API de Integración v1