Primeros pasos
Crea una llave, da de alta un cliente con su primera cuota y recibe un webhook cuando se pague.
Toma unos quince minutos. Los ejemplos usan curl y dos variables de entorno.
export MAKATEA_API=https://makatea.ai/api
export MAKATEA_KEY=mk_live_...
1. Saca una llave
En Makatea entra a Configuración → Desarrolladores → Nueva llave. Sólo el dueño o un administrador de la organización ve esa sección.
- Ponle el nombre del sistema que la va a usar.
- Elige los permisos.
readconsulta ywritecrea, cambia y borra. - Copia la llave al crearla. Empieza con
mk_live_y no se vuelve a mostrar.
Cada llamada lleva la llave en uno de estos encabezados.
Authorization: Bearer mk_live_...
X-API-Key: mk_live_...
Comprueba que el servicio contesta. Esta ruta no pide llave.
curl -s $MAKATEA_API/v1/status
2. Da de alta un cliente
external_ref es tu identificador del cliente. Es único por organización y sirve para buscarlo después sin guardar el id de Makatea.
curl -s -X POST $MAKATEA_API/v1/members \
-H "Authorization: Bearer $MAKATEA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: alta-cliente-1042" \
-d '{
"full_name": "Sofía Ramírez López",
"phone_e164": "+5215512345678",
"email": "sofia@ejemplo.mx",
"external_ref": "CLI-1042",
"identity": { "contrato": "PSG-1042" }
}'
La respuesta trae el cliente dentro de data. Guarda data.id para el siguiente paso.
{ "data": { "id": "6f1c…", "full_name": "Sofía Ramírez López", "external_ref": "CLI-1042", "state": "active" } }
Los campos de identity quedan disponibles como variables en las plantillas de mensaje.
3. Crea su primera cuota
Una cuota es un cobro con monto y fecha de vencimiento. Si la organización tiene un calendario de cobranza activo, la cuota entra a él y sus recordatorios se programan solos.
curl -s -X POST $MAKATEA_API/v1/billing-orders \
-H "Authorization: Bearer $MAKATEA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cuota-CLI-1042-2026-10" \
-d '{
"member_id": "6f1c…",
"amount": 1850,
"due_date": "2026-10-10",
"period_label": "Octubre 2026",
"external_ref": "CLI-1042-2026-10"
}'
Si la cuota es de un crédito, manda también capital_portion e interest_portion. Los dos van juntos y su suma no pasa de amount.
Para ver los recordatorios que quedaron programados:
curl -s "$MAKATEA_API/v1/sequence-runs?member_id=6f1c…" -H "Authorization: Bearer $MAKATEA_KEY"
4. Registra un pago
paid_at es el día en que entró el dinero. Puede ser pasado y nunca futuro. Un pago menor al saldo deja la cuota abierta con su abono.
curl -s -X POST $MAKATEA_API/v1/billing-orders/{id}/payments \
-H "Authorization: Bearer $MAKATEA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pago-SPEI-4471" \
-d '{ "amount": 1850, "paid_at": "2026-10-09", "method": "transfer", "reference": "SPEI-4471" }'
Al quedar pagada, la cuota sale del calendario y los recordatorios pendientes se cancelan.
5. Recibe webhooks
Registra un endpoint https con los eventos que te interesan, o * para todos.
curl -s -X POST $MAKATEA_API/v1/webhook-endpoints \
-H "Authorization: Bearer $MAKATEA_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://tu-sistema.mx/webhooks/makatea",
"events": ["billing_order.paid", "payment.received", "promise.broken"]
}'
La respuesta trae el secreto de firma whsec_… una sola vez. Guárdalo junto a la llave.
Cada evento llega como POST con este cuerpo.
{ "id": "evt…", "type": "payment.received", "created_at": "2026-10-09T15:02:11Z", "data": { } }
Verifica la firma antes de confiar en el cuerpo. El encabezado Makatea-Signature trae t (segundos Unix) y v1, el HMAC-SHA256 de t + "." + cuerpo crudo con tu secreto.
import crypto from "node:crypto";
// cuerpoCrudo: el cuerpo tal como llegó, antes de JSON.parse.
export function firmaValida(secreto, encabezado, cuerpoCrudo) {
const partes = Object.fromEntries(encabezado.split(",").map((p) => p.trim().split("=")));
const t = Number(partes.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
const esperado = crypto.createHmac("sha256", secreto).update(`${t}.${cuerpoCrudo}`).digest("hex");
const a = Buffer.from(esperado);
const b = Buffer.from(partes.v1 ?? "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Contesta con un 2xx en menos de 10 segundos. Si no, Makatea reintenta a 1 min, 5 min, 30 min, 2 h, 6 h y 24 h. Tras 8 intentos la entrega queda failed y se reintenta con POST /v1/webhook-deliveries/{id}/retry.
Un evento puede llegar dos veces o fuera de orden. Usa id para descartar el repetido.
Errores que vas a ver
Todo error trae la misma forma, con un request_id para pedir soporte.
{ "error": { "code": "validation_error", "message": "amount must be a positive number", "request_id": "…" } }
| Código | Cuándo pasa | Qué hacer |
|---|---|---|
401 | Falta la llave o no es válida | Revisa el encabezado y que la llave no esté revocada |
403 insufficient_scope | La llave no tiene el permiso | Crea una llave con write |
409 | El external_ref ya existe o la cuota ya está pagada | Busca el registro con ?external_ref= |
422 idempotency_key_reused | Misma Idempotency-Key con otro cuerpo | Usa una llave nueva por operación |
429 | Pasaste de 600 llamadas por minuto | Espera lo que diga Retry-After |
Siguiente
- Carga histórica para subir tu cartera actual.
- Conciliación diaria para cuadrar los pagos contra tu sistema.
- Referencia completa con cada ruta y cada campo.
Esta guía en markdown. Sigue con Carga histórica.