01Cómo funciona el circuito
Tu billetera envía suscripciones (el cliente invierte su saldo) y rescates (el cliente lo recupera) por API, a medida que ocurren. La plataforma las netea por cuenta comitente y, al horario de corte, arma un batch que — previa aprobación humana — se envía al Back Office de la ALyC. El efectivo de cada comitente queda siempre en 0: solo se mueve la posición en el fondo.
- Enviás órdenes → quedan
QUEUEDen el batch del día. - Al corte se congelan (
BATCHED) y se calcula el hash del detalle. - Un aprobador verifica y aprueba → los netos van al Back Office (
SENT). - Te notificamos por webhook (
batch.sent) y liquidamos el neto: positivo, nos transferís; negativo, te devolvemos.
02Credenciales que vas a recibir
| Credencial | Formato | Para qué |
|---|---|---|
| API key | sk_… |
Autentica cada request. Está atada a tu billetera: solo ves tus órdenes y batches. |
| Signing secret (opcional) | whsec_… |
Firma HMAC de tus requests, si tu key la exige (recomendado en producción). |
| Webhook secret | whsec_… |
Verificás con él la firma de los webhooks que te enviamos. |
401 API key expirada. Guardalas en un
secret manager — nunca en el código.03Autenticación y firma
Cada request lleva la API key en un header:
Authorization: Bearer sk_xxx # o alternativamente:
X-Api-Key: sk_xxx
Firma HMAC (si tu key la exige)
Agregá dos headers: X-Timestamp (epoch en segundos, tolerancia
±5 minutos) y X-Signature = HMAC-SHA256 en hexadecimal del string
"{timestamp}.{body}" con tu signing secret. Para GET el body es
la cadena vacía.
// Node.js
import { createHmac } from "node:crypto";
const ts = Math.floor(Date.now() / 1000);
const body = JSON.stringify(payload); // exactamente lo que envías
const signature = createHmac("sha256", SIGNING_SECRET)
.update(ts + "." + body)
.digest("hex");
// Headers: X-Timestamp: ts · X-Signature: signature
04Endpoints
| Método | Path | Descripción |
|---|---|---|
| GET | /api/v1/funds |
Catálogo de fondos activos (con fund_id, moneda, mínimos y último VCP). |
| POST | /api/v1/subscriptions |
Alta de suscripción (idempotente). |
| POST | /api/v1/redemptions |
Alta de rescate (idempotente). |
| GET | /api/v1/orders/{id} |
Estado de una orden. |
| POST | /api/v1/orders/{id}/cancel |
Anulación (solo antes del corte). |
| GET | /api/v1/batches/{id} |
Detalle de un corte: totales, hash y órdenes (para conciliar). |
| GET | /api/v1/accounts |
Rendimiento por cuenta comitente: saldo valorizado, ganancia y % por fondo. |
| GET | /api/v1/accounts/{comitente} |
Detalle de una cuenta + evolución histórica del saldo. |
Schemas completos, códigos de error y ejemplos por endpoint: Swagger.
05Crear una orden
curl -X POST {BASE_URL}/api/v1/subscriptions \
-H "Authorization: Bearer sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "sub-2026-07-28-000123",
"comitente": "COM-000123",
"amount": 150000.50,
"fund_id": "9be2…-uuid del fondo (GET /api/v1/funds)",
"client_id": "tu id interno del cliente",
"client_name": "Juan Pérez", // opcional
"external_ref": "op-987654", // opcional, tu referencia
"cvu": "0000003100010000000001" // opcional
}'
Idempotencia
La idempotency_key es obligatoria y única por orden (mín. 8
caracteres). Un reintento con la misma clave devuelve la misma
orden con replayed: true y status 200 (en
lugar de 201). Nunca duplica: reintentá con confianza ante
timeouts.
Estados de la orden
| Estado | Significado |
|---|---|
QUEUED | Recibida, en cola para el próximo corte. Se puede anular. |
BATCHED | Incluida en un corte, esperando aprobación. Ya no se anula. |
SENT | Enviada al Back Office (neteada por comitente). |
CANCELLED / REJECTED | Anulada por vos u operador / corte rechazado. |
06Rate limiting
Cada key tiene un máximo de requests por minuto. Al excederlo la API
responde 429 con Retry-After (segundos) y los
headers X-RateLimit-Limit, X-RateLimit-Remaining y
X-RateLimit-Reset. Implementá backoff exponencial respetando
Retry-After.
07Webhooks (te avisamos nosotros)
Configuranos una URL HTTPS y te notificamos los eventos en lugar de que hagas polling:
| Evento | Cuándo | Payload (data) |
|---|---|---|
batch.sent | Tu corte fue enviado al Back Office. | batch_id, business_date, detail_hash, cantidades y montos (suscripto, rescatado, neto). |
order.cancelled | Un operador anuló una orden tuya. | order_id, idempotency_key, comitente, type, amount, reason. |
test | Prueba de integración manual. | Mensaje de prueba. |
Cada entrega es un POST con body
{ event, created_at, data } y estos headers:
X-Webhook-Event: batch.sent
X-Webhook-Delivery: id único de la entrega (para deduplicar reintentos)
X-Webhook-Signature: t=1791234567,v1=<hmac hex>
Verificación de la firma
// Node.js — mismo esquema que la firma de requests
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(headers, rawBody, secret) {
const m = /t=(\d+),v1=([0-9a-f]+)/.exec(headers["x-webhook-signature"]);
if (!m) return false;
const expected = createHmac("sha256", secret)
.update(m[1] + "." + rawBody)
.digest("hex");
return timingSafeEqual(Buffer.from(expected), Buffer.from(m[2]));
}
2xx en
menos de 8 segundos (procesá async si hace falta). Ante error reintentamos
con backoff exponencial (30s → 1h, hasta 8 intentos). Deduplicá por
X-Webhook-Delivery: un mismo evento puede llegar más de una vez.08Checklist de go-live
- API key guardada en secret manager y probada contra
GET /api/v1/funds. - Firma HMAC implementada y validada (request de prueba con firma inválida →
401). idempotency_keyúnica por operación y reintentos ante timeout implementados.- Manejo de
429conRetry-After. - Endpoint de webhook desplegado: firma verificada, dedupe por delivery id, respuesta
2xx< 8s. - Webhook de prueba recibido OK (lo disparamos nosotros desde el panel).
- Conciliación diaria:
GET /api/v1/batches/{id}contra tu registro, usandodetail_hash.