ProviBet
Para desarrolladores

API de ProviBet

Una integración de servidor a servidor para consultar saldos y administrar créditos. Versión 1.

1. Autenticación

El administrador entrega un API Key, un API Secret y habilita las IPs de salida de tu backend. Una whitelist vacía deniega todo acceso. Se firman todas las consultas y escrituras, excepto GET /api/v1/status.

HeaderValor
X-API-KeyClave completa del cliente
X-TimestampUnix timestamp entero en segundos; reloj sincronizado, tolerancia máxima ±300 s
X-NonceValor aleatorio único de 16 a 128 caracteres: letras, números, guion o guion bajo
X-SignatureHMAC-SHA256 hexadecimal, minúsculas
X-Signature-VersionOpcional; si se envía, debe ser v1
Idempotency-KeyObligatorio para cargas y retiros. Clave única de 16 a 128 caracteres, mismo alfabeto del nonce

Cadena a firmar

Uní estos ocho campos con LF (\n), sin salto final. El API Secret se usa como texto literal, sin decodificarlo.

v1
API_KEY_COMPLETA
METODO_HTTP_EN_MAYUSCULAS
RUTA_CON_QUERY_EXACTA
TIMESTAMP
NONCE
IDEMPOTENCY_KEY_O_VACIO
SHA256_HEXADECIMAL_DEL_BODY_CRUDO

Firmá exactamente los bytes enviados. Para GET, el body es vacío. Incluí el query string en su orden y codificación originales. No reserialices JSON después de firmar. Un reintento usa nonce y timestamp nuevos, conservando la clave de idempotencia y los mismos datos.

2. Endpoints

Método y rutaPermisoResultado
GET /api/v1/statusPúblicoEstado básico
GET /api/v1/catalogcatalog:readCatálogo con IDs propios
GET /api/v1/balancebalance:readSaldo disponible y reservado del cliente
GET /api/v1/destinationsbalance:readDestinos asignados a tu cliente
POST /api/v1/credits/addcredits:addCarga a un destino autorizado
POST /api/v1/credits/removecredits:removeRetiro de un destino autorizado
GET /api/v1/transactionstransactions:readHistorial del cliente
GET /api/v1/transaction/{id}transactions:readEstado de una operación propia

Destinos y transacciones aceptan limit (1–100, predeterminado 50) y before (UUID de next_before en la consulta anterior). Las transferencias entre clientes/subagentes no están disponibles: POST /api/v1/transfer requiere autenticación y permiso balance:read; responde HTTP 422 OPERATION_NOT_SUPPORTED una vez superados esos controles. Las altas de destinos se coordinan con el administrador.

3. Saldos y créditos

{"success":true,"data":{"available":"1500.00","reserved":"200.00","unit":"credits","scale":2}}

Los créditos no representan automáticamente una moneda fiduciaria ni implican una conversión monetaria. Una carga reserva saldo del cliente; una confirmación lo consume. Un retiro confirmado acredita la wallet del cliente. Los clientes no pueden autoacreditarse saldo: las recargas comerciales las registra el administrador.

Solicitar una carga

POST /api/v1/credits/add
Content-Type: application/json
Idempotency-Key: 95c895bc-d8fc-4359-a841-e29f4150c0ee

{"destination_id":"0bfa0cc3-d659-4ecb-bf7d-0d8d34df96af","amount":"100.00","reference":"orden-1038"}

El destino debe pertenecer al cliente autenticado. El importe es mayor a cero, máximo 1000000000.00, sin exponentes, separadores de miles ni más de dos decimales. reference es opcional, máximo 128 caracteres. El retiro usa el mismo formato en /credits/remove.

HTTP 202
{"success":true,"data":{"id":"31f1e19e-16c6-4de7-915d-906a7d124c8a","status":"pending","kind":"add","amount":"100.00","status_url":"/api/v1/transaction/31f1e19e-16c6-4de7-915d-906a7d124c8a"}}

Idempotencia y estados

La misma clave y datos equivalentes devuelven la aceptación original HTTP 202 y el mismo UUID, sin crear otra operación. El reintento sigue sujeto a autenticación, permisos y controles operativos vigentes. Reutilizar una clave con datos distintos produce HTTP 409. Consultá el recurso individual para obtener el estado actualizado.

EstadoInterpretación
pendingAceptada, espera procesamiento
processingEn proceso
pending_verificationResultado pendiente de confirmar
completedConfirmada
failedRechazada o no enviada

4. Límites y errores

Cada cliente tiene límites de consultas y escrituras por minuto, con controles por cliente, clave, IP y ruta. El administrador configura esos límites. HTTP 429 incluye Retry-After. Los cambios de acceso se aplican a las nuevas solicitudes. Todas las respuestas incluyen X-Request-ID para soporte.

{"success":false,"error":{"code":"IP_NOT_ALLOWED","message":"Access denied"},"request_id":"UUID"}

Códigos frecuentes: INVALID_API_KEY, INVALID_SIGNATURE, IP_NOT_ALLOWED, DUPLICATE_REQUEST, RATE_LIMIT_EXCEEDED, FORBIDDEN, INVALID_REQUEST, INSUFFICIENT_BALANCE, IDEMPOTENCY_CONFLICT, DESTINATION_BUSY, OPERATIONS_PAUSED y PROVIDER_TEMPORARILY_UNAVAILABLE. Un HTTP 5xx no justifica enviar la misma intención con una clave nueva.

5. Ejemplos

Node.js
import { createHash, createHmac, randomBytes } from 'node:crypto';
const key = process.env.PROVIBET_API_KEY;
const secret = process.env.PROVIBET_API_SECRET;
const origin = process.env.PROVIBET_ORIGIN;
const method = 'GET', target = '/api/v1/balance', body = '';
const timestamp = String(Math.floor(Date.now() / 1000));
const nonce = randomBytes(24).toString('hex');
const idempotency = ''; // Para POST, generar y guardar una clave antes del primer envío.
const digest = createHash('sha256').update(body).digest('hex');
const canonical = ['v1', key, method, target, timestamp, nonce, idempotency, digest].join('\n');
const signature = createHmac('sha256', secret).update(canonical).digest('hex');
const headers = {'X-API-Key':key,'X-Timestamp':timestamp,'X-Nonce':nonce,'X-Signature':signature};
if (idempotency) headers['Idempotency-Key'] = idempotency;
const response = await fetch(origin + target, {method, headers, redirect:'error'});
console.log(response.status, await response.json());
PHP 8.3
<?php
$key = getenv('PROVIBET_API_KEY'); $secret = getenv('PROVIBET_API_SECRET');
$target = '/api/v1/balance'; $body = ''; $method = 'GET';
$timestamp = (string) time(); $nonce = bin2hex(random_bytes(24)); $idem = '';
$canonical = implode("\n", ['v1',$key,$method,$target,$timestamp,$nonce,$idem,hash('sha256',$body)]);
$signature = hash_hmac('sha256', $canonical, $secret);
$ch = curl_init(getenv('PROVIBET_ORIGIN').$target);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,
 CURLOPT_TIMEOUT => 20, CURLOPT_FOLLOWLOCATION => false,
 CURLOPT_HTTPHEADER => ["X-API-Key: $key","X-Timestamp: $timestamp",
 "X-Nonce: $nonce","X-Signature: $signature"]]);
$result = curl_exec($ch);
if ($result === false) throw new RuntimeException('Error de conexión');
echo $result;
cURL · Bash
target='/api/v1/balance'
timestamp=$(date +%s)
nonce=$(openssl rand -hex 24)
digest=$(printf '' | openssl dgst -sha256 -r | cut -d' ' -f1)
signature=$(printf 'v1\n%s\nGET\n%s\n%s\n%s\n\n%s' "$PROVIBET_API_KEY" "$target" "$timestamp" "$nonce" "$digest" | openssl dgst -sha256 -hmac "$PROVIBET_API_SECRET" -r | cut -d' ' -f1)
curl --proto '=https' --max-time 20 "$PROVIBET_ORIGIN$target" \
 -H "X-API-Key: $PROVIBET_API_KEY" -H "X-Timestamp: $timestamp" \
 -H "X-Nonce: $nonce" -H "X-Signature: $signature"

Ejemplo para desarrollo privado. En producción usá tu lenguaje para evitar argumentos de proceso con secretos.

Catálogo

Devuelve items con id, name y status, más updated_at y stale. Los IDs son propios de ProviBet. El caché mantiene disponibilidad durante interrupciones temporales; después de 24 horas sin actualización se rechaza la consulta.