Integra envíos de dinero entre usuarios en minutos. API REST con autenticación por API key, webhooks y rate limiting listo para producción.
Tres pasos para enviar tu primer pago.
# POST /auth/login
curl -X POST https://api.payg0.io/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"tu@email.com","password":"tu-password"}'
# Activa modo dev primero
curl -X PATCH https://api.payg0.io/users/developer-mode \
-H 'Authorization: Bearer {token}' \
-d '{"enabled": true}'
# Genera tu API key
curl -X POST https://api.payg0.io/keys \
-H 'Authorization: Bearer {token}' \
-d '{"name": "Mi app"}'
# Enviar $100 MXN a un usuario
curl -X POST https://api.payg0.io/payments/send \
-H 'X-API-Key: pyg0_test_xxxxxxxxxxxxx' \
-H 'Content-Type: application/json' \
-d '{"recipient": "@carlos", "amount": 100.00}'
# Response
{
"id": "uuid...",
"status": "COMPLETED",
"reason": "transferred",
"amount": "100.00"
}
Dos métodos según el contexto.
X-API-KeyIdeal para integraciones server-to-server y agentes de IA. Genera tus keys en POST /keys.
X-API-Key: pyg0_test_a1b2c3d4e5f6g7h8
Para sesiones de usuario. Token de 24 horas obtenido en POST /auth/login.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Sandbox vs Producción:
Las API keys de sandbox tienen prefijo pyg0_test_. En producción usarán pyg0_live_.
En sandbox el dinero es simulado y no hay movimientos bancarios reales.
Todos los endpoints disponibles en la API.
| Método | Ruta | Descripción | Rate limit |
|---|---|---|---|
| POST | /auth/register | Crear cuenta | 10/min |
| POST | /auth/login | Obtener JWT | 10/min |
| GET | /auth/me | Perfil del usuario autenticado | 30/min |
| Método | Ruta | Descripción | Rate limit |
|---|---|---|---|
| GET | /wallet/balance | Saldo disponible, retenido y total | 30/min |
| Método | Ruta | Descripción | Rate limit |
|---|---|---|---|
| POST | /payments/send | Enviar pago a nickname o email | 5/min |
| GET | /payments/history | Historial paginado con filtros | 30/min |
| GET | /payments/{id} | Detalle de transacción | 30/min |
| POST | /payments/{id}/cancel | Cancelar pago PENDING (solo emisor) | 30/min |
| Método | Ruta | Descripción | Rate limit |
|---|---|---|---|
| GET | /users/lookup?q= | Buscar usuario por nickname o email | 30/min |
| PATCH | /users/developer-mode | Activar/desactivar modo desarrollador | 30/min |
| Método | Ruta | Descripción | Rate limit |
|---|---|---|---|
| POST | /keys | Crear API key (full key solo en este response) | 30/min |
| GET | /keys | Listar API keys activas | 30/min |
| DELETE | /keys/{id} | Revocar API key | 30/min |
| Método | Ruta | Descripción | Rate limit |
|---|---|---|---|
| POST | /webhooks | Registrar endpoint de webhook | 10/min |
| GET | /webhooks | Listar webhooks activos | 30/min |
| DELETE | /webhooks/{id} | Eliminar webhook | 30/min |
Recibe notificaciones en tiempo real cuando ocurre un evento de pago.
payment.completedpayment.pendingpayment.failedpayment.cancelledpayment.expiredcurl -X POST https://api.payg0.io/webhooks \
-H 'X-API-Key: pyg0_test_xxxx' \
-d '{
"url": "https://tu-app.com/webhooks/payg0",
"events": ["payment.completed", "payment.failed"]
}'
Cada request incluye el header X-Payg0-Signature: sha256={hmac}. Verifica con el secret que recibiste al crear el webhook.
import hmac, hashlib
def verify_signature(payload: bytes, secret: str, signature: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
# En tu handler:
body = await request.body()
sig = request.headers["X-Payg0-Signature"]
if not verify_signature(body, WEBHOOK_SECRET, sig):
raise HTTPException(401)
Enviar un pago en distintos lenguajes.
import httpx
client = httpx.Client(
base_url="https://api.payg0.io",
headers={"X-API-Key": "pyg0_test_xxxxxxxxxxxxx"},
)
# Consultar saldo
balance = client.get("/wallet/balance").json()
print(f"Disponible: ${balance['available_balance']} MXN")
# Enviar pago
response = client.post("/payments/send", json={
"recipient": "@carlos",
"amount": 150.00,
"description": "Pago por servicio",
})
tx = response.json()
print(f"Transacción {tx['id']}: {tx['status']}")
const BASE = "https://api.payg0.io";
const HEADERS = {
"X-API-Key": "pyg0_test_xxxxxxxxxxxxx",
"Content-Type": "application/json",
};
// Consultar saldo
const balance = await fetch(`${BASE}/wallet/balance`, { headers: HEADERS })
.then(r => r.json());
console.log(`Disponible: $${balance.available_balance} MXN`);
// Enviar pago
const tx = await fetch(`${BASE}/payments/send`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({ recipient: "@carlos", amount: 150 }),
}).then(r => r.json());
console.log(`Transacción ${tx.id}: ${tx.status}`);
# Saldo
curl https://api.payg0.io/wallet/balance \
-H "X-API-Key: pyg0_test_xxxxxxxxxxxxx"
# Enviar pago
curl -X POST https://api.payg0.io/payments/send \
-H "X-API-Key: pyg0_test_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"recipient":"@carlos","amount":150,"description":"Pago"}'
# Historial
curl "https://api.payg0.io/payments/history?status=COMPLETED&limit=10" \
-H "X-API-Key: pyg0_test_xxxxxxxxxxxxx"
Los límites se aplican por API key, sesión JWT o IP.
| Operación | Límite |
|---|---|
POST /payments/send | 5 por minuto |
| GET endpoints en general | 30 por minuto |
POST /webhooks | 10 por minuto |
GET /api/usage | 20 por minuto |
| Auth (login / register) | 10 por minuto |
Al superar el límite recibirás 429 Too Many Requests. El header Retry-After indica cuándo reintentar.
Todos los errores retornan JSON con el campo detail.
| Código | Significado |
|---|---|
| 400 | Bad Request — parámetros inválidos |
| 401 | Unauthorized — token o API key inválida o expirada |
| 403 | Forbidden — sin permisos (ej. modo dev no activo) |
| 404 | Not Found — recurso no encontrado |
| 409 | Conflict — email o nickname ya registrado |
| 422 | Unprocessable — fondos insuficientes o datos inválidos |
| 429 | Too Many Requests — rate limit excedido |
| 500 | Internal Server Error — error interno inesperado |