¿Qué resuelve esta API?
Cuando un comprador paga en tu checkout con el botón o link de pago Payefy, tu sistema normalmente se entera del resultado por el redirect del navegador. Si el comprador cierra la página antes de regresar, el cargo puede haberse procesado sin que tu sistema lo sepa.
Con esta API tu backend consulta directamente a Payefy el estado real de una transacción y puede continuar su flujo (emitir el boleto, entregar el producto, conciliar) con una respuesta verídica al momento: si la transacción aún no está en nuestra base, Payefy la verifica contra el procesador antes de responder.
Ambientes
| Ambiente | Base URL |
|---|---|
| Pruebas (sandbox) | https://sandbox-panel.payefy.me |
| Producción | https://panel.payefy.me |
Recomendamos certificar primero en sandbox con las credenciales de prueba que te entreguemos.
Credenciales
| Credencial | Formato | Uso |
|---|---|---|
| API Key | pk_… | Identifica tu llave. Viaja en el header X-Api-Key. |
| Secret | sk_… | Firma cada request (HMAC). Nunca viaja en el request y solo se muestra una vez al generarse. |
- Guarda el secret en un gestor de secretos o variable de entorno; nunca en código fuente, frontend ni logs.
- Cada llave está acotada a tus comercios: no puede consultar transacciones de terceros.
- Si el secret se compromete, avísanos: desactivamos la llave y generamos una nueva.
Autenticación y firma
Cada request lleva tres headers:
| Header | Contenido |
|---|---|
X-Api-Key | Tu API Key (pk_…) |
X-Timestamp | Epoch actual en milisegundos (ej. 1766000000000) |
X-Signature | HMAC-SHA256(secret, "{X-Timestamp}.{body}") en hexadecimal minúsculas |
Cómo se calcula la firma
body = JSON.stringify(payload) // los bytes EXACTOS que vas a enviar cadena = `${timestamp}.${body}` // timestamp + "." + body X-Signature = HMAC_SHA256(secret, cadena).hex() // hexadecimal minúsculas
401 {"error":"No autorizado"} sin más detalle, por seguridad.Vector de prueba
Valida tu implementación de la firma antes de conectarte — con estos insumos, tu código debe producir exactamente esta firma:
secret: sk_ejemplo_no_usar_en_produccion timestamp: 1766000000000 body: {"reference":"PED-A1B2C3"} cadena: 1766000000000.{"reference":"PED-A1B2C3"} X-Signature: 8edc273902e6999ed97b24e41c37d29db176e6f58b4b9f574b152b3ce7affc7a
Endpoint
POST {base}/api/partner/v1/transactions/status
Content-Type: application/jsonUn solo endpoint con tres modos de consulta, según el body:
1. Por referencia Recomendado
La referencia que enviaste al crear el cargo, o la reference que regresa el redirect del botón.
{ "reference": "PED-A1B2C3" }2. Por identificador del procesador
{ "id": "486438866654" }3. Por rango de fechas Conciliación
Lista las transacciones de tus comercios en un rango (máximo 48 horas), con filtro opcional de monto exacto. Útil para conciliar compras "en el limbo" contra lo realmente cobrado.
{ "from": "2026-08-18T14:00:00Z", "to": "2026-08-18T16:00:00Z", "amount": 850 }Regresa hasta 500 transacciones, de la más reciente a la más antigua, en { "count": …, "transactions": [ … ] }.
Respuesta y campos
Encontrada
{
"found": true,
"transaction": {
"reference": "PED-A1B2C3",
"id": "486438866654",
"status": "aprobada",
"approved": true,
"amount": 850.00,
"currency": "MXN",
"auth_code": "605599",
"date": "2026-08-18T17:25:16.000Z",
"card": { "bin": "411111", "last4": "1111" },
"method": "ecommerce",
"brand": "VISA",
"merchant": { "id": 8721364, "name": "MI COMERCIO" }
}
}No existe
{ "found": false }Si no existe ni en Payefy ni en el procesador. Puedes confiar en este resultado para tu flujo.
Importante
Si la transacción no está en nuestra base, Payefy la verifica contra el procesador antes de responder. Por esta verificación la respuesta puede tardar algunos segundos en el peor caso: configura un timeout de 15 segundos.| Campo | Tipo | Descripción |
|---|---|---|
reference | string | null | La referencia del cargo (la que enviaste, o la generada por el procesador). |
id | string | Identificador único de la transacción en el procesador. |
status | string | aprobada · rechazada · reembolso |
approved | boolean | Atajo: true solo si status = "aprobada". |
amount / currency | number / string | Monto con dos decimales; siempre MXN. |
auth_code | string | null | Código de autorización bancario. |
date | string | Fecha/hora de la transacción (ISO-8601, UTC). |
card.bin / card.last4 | string | null | Primeros 6 y últimos 4 dígitos de la tarjeta. |
method / brand | string | null | Canal y marca (VISA, MASTERCARD, AMEX). |
merchant.id / .name | number / string | Comercio al que pertenece la venta. |
Errores
| HTTP | Cuándo | Qué hacer |
|---|---|---|
| 400 | Body inválido (sin criterios, rango > 48 h, fechas mal formadas, monto inválido). | Corrige el request; el mensaje de error lo indica. |
| 401 | Falta un header, firma inválida, timestamp fuera de ventana o llave desactivada. | Revisa la firma con el vector de prueba y el reloj del servidor. |
| 429 | Más de 120 requests por minuto con tu llave. | Espera y reintenta; agrega backoff. |
| 500 | Error interno. | Reintenta con backoff; si persiste, contáctanos. |
Los errores 4xx regresan { "error": "descripción" }.
Buenas prácticas
- Flujo recomendado para el checkout: si tu página no recibe el redirect en N minutos (compra "en el limbo"), consulta por tu
reference. Conapproved: true, entrega el boleto/producto; confound: falseoapproved: false, marca la compra como no pagada. - Conciliación diaria: una consulta por rango de tu día operativo y cruza contra tus órdenes — reemplaza la validación manual.
- Reintentos: la consulta es de solo lectura; es seguro reintentarla las veces necesarias.
- Timeout: 15 segundos (la verificación contra el procesador puede tomar unos segundos).
- Reloj: sincroniza tu servidor por NTP; un desfase mayor a 5 minutos produce 401.
- Secret: trátalo como contraseña. No va en el frontend, ni en repositorios, ni en logs.
Ejemplos de código
BODY='{"reference":"PED-A1B2C3"}' TS=$(($(date +%s) * 1000)) SIG=$(printf '%s' "$TS.$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //') curl -s -X POST "https://sandbox-panel.payefy.me/api/partner/v1/transactions/status" \ -H "Content-Type: application/json" \ -H "X-Api-Key: $API_KEY" -H "X-Timestamp: $TS" -H "X-Signature: $SIG" \ -d "$BODY"
const crypto = require('crypto'); async function consultarTransaccion(reference){ const body = JSON.stringify({ reference }); const ts = String(Date.now()); const firma = crypto.createHmac('sha256', process.env.PAYEFY_SECRET) .update(`${ts}.${body}`).digest('hex'); const res = await fetch('https://sandbox-panel.payefy.me/api/partner/v1/transactions/status', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': process.env.PAYEFY_API_KEY, 'X-Timestamp': ts, 'X-Signature': firma, }, body, // enviar EXACTAMENTE la cadena firmada signal: AbortSignal.timeout(15000), }); return res.json(); // { found, transaction? } }
function consultarTransaccion(string $reference): array {
$body = json_encode(['reference' => $reference]);
$ts = (string) round(microtime(true) * 1000);
$sig = hash_hmac('sha256', $ts . '.' . $body, getenv('PAYEFY_SECRET'));
$ch = curl_init('https://sandbox-panel.payefy.me/api/partner/v1/transactions/status');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body, // enviar EXACTAMENTE la cadena firmada
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Api-Key: ' . getenv('PAYEFY_API_KEY'),
'X-Timestamp: ' . $ts,
'X-Signature: ' . $sig,
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$res = curl_exec($ch); curl_close($ch);
return json_decode($res, true);
}import hashlib, hmac, json, os, time
import requests
def consultar_transaccion(reference: str) -> dict:
body = json.dumps({"reference": reference}, separators=(",", ":"))
ts = str(int(time.time() * 1000))
firma = hmac.new(os.environ["PAYEFY_SECRET"].encode(),
f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
r = requests.post(
"https://sandbox-panel.payefy.me/api/partner/v1/transactions/status",
data=body, # enviar EXACTAMENTE la cadena firmada
headers={"Content-Type": "application/json",
"X-Api-Key": os.environ["PAYEFY_API_KEY"],
"X-Timestamp": ts, "X-Signature": firma},
timeout=15)
return r.json()Próximamente: webhooks
Soporte
Escríbenos con tu X-Api-Key (nunca el secret), la fecha/hora del request y el x-request-id que regresa cada respuesta — con eso rastreamos cualquier consulta en nuestros logs. soporte@payefy.me
© Payefy · Documentación Técnica · Versión 1.0, agosto 2026