Introducción a la API
Esta guía te ayudará a entender los conceptos básicos para integrar la API de GalioPay en tu aplicación.
URL Base
Todas las peticiones a la API deben dirigirse a:
https://pay.galio.app/api
Autenticacion
La API publica de GalioPay utiliza credenciales de cliente. Debes enviar API Key y Client ID en cada request autenticado.
Headers de autenticacion
Authorization: Bearer {TU_API_KEY}
x-client-id: {TU_CLIENT_ID}
Ejemplo de autenticación
const response = await fetch("https://pay.galio.app/api/payment-links", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer TU_API_KEY_AQUI",
"x-client-id": "TU_CLIENT_ID_AQUI",
},
body: JSON.stringify({
// ... datos de la petición
}),
});
Formatos de datos
La API acepta y devuelve datos en formato JSON.
Content-Type
Todas las peticiones deben incluir:
Content-Type: application/json
Códigos de respuesta HTTP
| Código | Significado | Descripción |
|---|---|---|
| 200 | OK | La petición fue exitosa |
| 201 | Created | Recurso creado exitosamente |
| 400 | Bad Request | Datos de entrada inválidos |
| 401 | Unauthorized | API Key inválida o faltante |
| 404 | Not Found | Recurso no encontrado |
| 500 | Internal Server Error | Error interno del servidor |
Manejo de errores
Cuando ocurre un error, la API devuelve una respuesta con el siguiente formato:
{
"error": "Descripción del error"
}
Webhooks
GalioPay envía webhooks con POST cuando cambia el estado del pago.
Destino del webhook (orden de prioridad):
notificationUrldel payment link (si fue enviado enPOST /api/payment-linksoPUT /api/payment-links/{id})notificationUrldel cliente (fallback)
Si no hay URL configurada en ninguno de los dos niveles, no se envía webhook.
Firma HMAC opcional
La firma de webhooks es opcional.
Cuando la firma HMAC está activada para tu cuenta, GalioPay agrega estos headers a cada webhook:
X-GalioPay-Event-Id: wh_evt_67a8f1b2c3d4e5f6a7b8c9d0_payment
X-GalioPay-Timestamp: 1768046400
X-GalioPay-Signature: v1=9f1c...
La firma se calcula con tu secreto de webhook:
HMAC_SHA256(timestamp + "." + raw_body, webhook_secret)
raw_body debe ser el body exacto recibido en la request, antes de parsearlo como JSON. No reconstruyas el JSON para validar la firma, porque puede cambiar el orden o formato de los campos.
Ejemplo de validación en Node.js/Express:
import crypto from "crypto";
import express from "express";
const app = express();
app.post(
"/webhooks/galiopay",
express.raw({ type: "application/json" }),
(req, res) => {
const webhookSecret = process.env.GALIOPAY_WEBHOOK_SECRET;
const timestamp = req.header("X-GalioPay-Timestamp");
const signatureHeader = req.header("X-GalioPay-Signature") || "";
const expectedSignature = crypto
.createHmac("sha256", webhookSecret)
.update(`${timestamp}.${req.body.toString("utf8")}`)
.digest("hex");
const receivedSignature = signatureHeader.replace("v1=", "");
if (receivedSignature !== expectedSignature) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body.toString("utf8"));
// Usa X-GalioPay-Event-Id para idempotencia.
res.sendStatus(200);
},
);
Recomendaciones:
- Rechaza timestamps demasiado antiguos, por ejemplo mayores a 5 minutos.
- Guarda
X-GalioPay-Event-Idpara no procesar dos veces el mismo evento. - Responde
200si ya procesaste eseeventId, para evitar reintentos innecesarios.
Los POST posibles que puedes recibir
| Caso | status | Cuándo se envía |
|---|---|---|
| Pago aprobado | approved | Cuando un pago se acredita correctamente |
| Pago reembolsado | refunded | Cuando se completa un reembolso |
Payload de pago (approved)
{
"id": "67a8f1b2c3d4e5f6a7b8c9d0",
"paymentMethodId": "TRANSFER",
"amount": 15000,
"netAmount": 14650,
"moneyReleaseDate": "2026-02-12T00:00:00.000Z",
"currency": "ARS",
"status": "approved",
"sandbox": false,
"date": "2026-02-10T14:21:00.000Z",
"referenceId": "orden-456"
}
Payload de reembolso (refunded)
{
"id": "67a8f1b2c3d4e5f6a7b8c9d0",
"paymentMethodId": "TRANSFER",
"amount_refunded": 15000,
"refund_type": "total",
"refund_reason": "Cliente solicito devolucion",
"status": "refunded",
"currency": "ARS",
"sandbox": false,
"date": "2026-02-12T10:30:00.000Z",
"referenceId": "orden-456"
}
Ejemplos de errores comunes
Error de validación (400):
{
"error": "Items array is required"
}
API Key inválida (401):
{
"error": "Unauthorized"
}
Recurso no encontrado (404):
{
"error": "Payment link not found"
}
Ejemplo completo
Aquí tienes un ejemplo completo de cómo hacer una petición autenticada:
cURL
curl -X POST https://pay.galio.app/api/payment-links \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_API_KEY_AQUI" \
-H "x-client-id: TU_CLIENT_ID_AQUI" \
-d '{
"items": [
{
"title": "Producto de ejemplo",
"quantity": 1,
"unitPrice": 1000,
"currencyId": "ARS"
}
],
"referenceId": "orden-123",
"backUrl": {
"success": "https://tusitio.com/exito",
"failure": "https://tusitio.com/error"
}
}'
JavaScript (Fetch)
async function crearLinkDePago() {
const apiKey = "TU_API_KEY_AQUI";
const clientId = "TU_CLIENT_ID_AQUI";
const datos = {
items: [
{
title: "Producto de ejemplo",
quantity: 1,
unitPrice: 1000,
currencyId: "ARS",
},
],
referenceId: "orden-123",
backUrl: {
success: "https://tusitio.com/exito",
failure: "https://tusitio.com/error",
},
};
try {
const response = await fetch("https://pay.galio.app/api/payment-links", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
"x-client-id": clientId,
},
body: JSON.stringify(datos),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
const resultado = await response.json();
console.log("Link creado:", resultado.url);
} catch (error) {
console.error("Error:", error.message);
}
}
Próximos pasos
- Aprende a crear links de pago
- Aprende a consultar y reembolsar pagos