Developers

API de Webhooks

Conectá tu sistema con tu tienda PedimeYa y mantené el inventario sincronizado en tiempo real. Cuando vendés un producto en cualquiera de los dos lados, el otro se entera al instante — todo identificado por el SKU de cada producto.

Contenido 1. Cómo funciona 2. Credenciales y autenticación 3. Firma de las peticiones (HMAC) 4. Webhook entrante — avisarnos de una venta 5. Webhooks salientes — te avisamos de una venta 6. Cómo resolvemos el SKU 7. Códigos de respuesta 8. Buenas prácticas

1. Cómo funciona

La integración es bidireccional y se apoya en el SKU como clave común entre ambos sistemas:

Toda la comunicación es sobre HTTPS, autenticada con una API key y firmada con HMAC-SHA256 para garantizar integridad y descartar reenvíos (replay).

La URL base de la API es https://api.pedimeya.com. Si usás un dominio propio, reemplazala por el que te indicamos en el panel.

2. Credenciales y autenticación

Desde el panel de administración, en Configuración → Developers, creás una integración. Al crearla obtenés, una sola vez:

Guardá ambos valores de forma segura: la apiKey se almacena hasheada y el signingSecret solo se muestra al crearlo o al rotarlo. Si los perdés, podés regenerarlos desde el panel (esto invalida los anteriores).

La API key viaja en el header Authorization:

Authorization: Bearer pmy_live_xxxxxxxxxxxxxxxxxxxxxxxx

3. Firma de las peticiones (HMAC)

Cada petición (entrante o saliente) incluye el header X-PedimeYa-Signature con este formato:

X-PedimeYa-Signature: t=1716760000,v1=4f2a...e9c1

Donde:

Para verificar (o generar) la firma, calculá el HMAC sobre el cuerpo exacto que viaja en la petición (sin re-serializar el JSON) y compará en tiempo constante. Rechazá la petición si el timestamp difiere más de 5 minutos respecto de tu reloj — eso evita ataques de replay.

Verificación en Node.js

const crypto = require('crypto');

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
  const t = Number(parts.t);
  if (Math.abs(Date.now() / 1000 - t) > 300) return false; // anti-replay
  const expected = crypto.createHmac('sha256', secret)
    .update(`${t}.${rawBody}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Verificación en PHP

function verify(string $rawBody, string $header, string $secret): bool {
    parse_str(str_replace(',', '&', $header), $p);
    if (abs(time() - (int)$p['t']) > 300) return false; // anti-replay
    $expected = hash_hmac('sha256', $p['t'] . '.' . $rawBody, $secret);
    return hash_equals($expected, $p['v1']);
}

4. Webhook entrante — avisarnos de una venta

POST/v1/webhooks/inbound

Llamá a este endpoint desde tu sistema cuando vendas un producto, para que descontemos el stock del SKU en tu tienda PedimeYa.

Headers

Authorization: Bearer pmy_live_xxxxxxxxxxxx
X-PedimeYa-Signature: t=1716760000,v1=...
Content-Type: application/json

Cuerpo

{
  "event_id": "venta-9f3a-0012",   // identificador único tuyo (idempotencia)
  "event": "product.sold",
  "sku": "REM-AZUL-M",
  "quantity": 2,
  "occurred_at": "2026-05-26T14:03:00Z"  // opcional (ISO 8601)
}

Ejemplo con curl

curl -X POST https://api.pedimeya.com/v1/webhooks/inbound \
  -H "Authorization: Bearer $PMY_API_KEY" \
  -H "X-PedimeYa-Signature: t=1716760000,v1=$SIG" \
  -H "Content-Type: application/json" \
  -d '{"event_id":"venta-9f3a-0012","event":"product.sold","sku":"REM-AZUL-M","quantity":2}'

Respuesta

{ "status": "applied", "sku": "REM-AZUL-M", "quantity": 2, "remaining_stock": 18 }

Posibles valores de status: applied (stock descontado), duplicate (ya habíamos procesado ese event_id), sku_not_found (no hay producto con ese SKU) o ignored (tipo de evento no soportado). Todos devuelven HTTP 200 — no reintentes ante sku_not_found.

Idempotencia: mandá un event_id único por venta. Si reintentás el mismo evento, lo detectamos y no descontamos stock dos veces.

5. Webhooks salientes — te avisamos de una venta

Cuando se concreta una venta en tu tienda, hacemos un POST a la URL que configuraste en la integración. Configurá esa URL y suscribí el evento order.sale desde el panel.

Headers que enviamos

X-PedimeYa-Signature: t=1716760000,v1=...
X-PedimeYa-Event: order.sale
X-PedimeYa-Delivery: 7c9e6a4b-...   // id único de esta entrega
Content-Type: application/json
User-Agent: PedimeYa-Webhooks/1.0

Cuerpo

{
  "event_id": "7c9e6a4b-1d2e-4f55-9aa1-3b8c0d6e5f21",
  "event": "order.sale",
  "occurred_at": "2026-05-26T14:05:12Z",
  "data": {
    "order_id": "a1b2c3d4-...",
    "invoice": "INV-a1b2c3d4",
    "items": [
      { "sku": "REM-AZUL-M", "quantity": 1, "product_id": "…", "variant_label": "Azul / M", "unit_price": "8990.00" }
    ]
  }
}

Respondé con un código 2xx lo antes posible (idealmente bajo 10 segundos). Si respondés otra cosa o no respondés, reintentamos.

Reintentos

Si la entrega falla, reintentamos hasta 8 veces con backoff exponencial (5s, 10s, 20s… hasta ~10 minutos). Cada entrega lleva el mismo event_id, así que usalo como clave de idempotencia para no procesar la misma venta dos veces. Las entregas agotadas quedan registradas en el panel para inspección.

6. Cómo resolvemos el SKU

Al recibir un evento entrante buscamos el SKU en este orden y descontamos del primero que coincida:

El stock nunca baja de cero. Asegurate de que los SKU sean únicos y coincidan exactamente (distinguimos mayúsculas/minúsculas) entre ambos sistemas.

7. Códigos de respuesta

CódigoSignificado
200Procesado. Mirá el campo status del cuerpo.
400Cuerpo inválido (falta event_id, sku o quantity no es un entero positivo).
401API key ausente/ inválida, o firma incorrecta / fuera de la ventana de tiempo.
500Error interno al procesar. Podés reintentar.

8. Buenas prácticas

¿Dudas para integrarte? Escribinos a contacto@pedimeya.com.