Conectá tu sistema
Para que el stock se sincronice solo y nadie compre algo que ya no tenés.
Si el comercio ya tiene su propio sistema de stock, punto de venta o página, no tiene sentido que cargue las cantidades dos veces. Esta API existe para eso: su sistema manda el stock, Super Oferta lo refleja, y cuando alguien compra le avisamos de vuelta.
Antes de empezar
- Pedí que te habiliten la API desde Panel → Funciones → API y webservices.
- Generá una clave en Panel → Integraciones. Se muestra una sola vez.
- Probá que anda con el
/pingde más abajo.
La clave va en la cabecera de cada pedido. Nunca la pongas en el navegador ni en una app de celular: desde ahí cualquiera la lee.
Authorization: Bearer so_live_ab12cd34_...Probar que la clave anda
curl https://superoferta.com.ar/api/v1/ping \
-H "Authorization: Bearer TU_CLAVE"{
"ok": true,
"comercio": { "id": "…", "nombre": "Panadería La Esquina", "estado": "activo" },
"clave": { "ambiente": "live", "permisos": ["ofertas:leer", "stock:escribir", …] },
"sincronizacion": { "ultima": null, "tolerancia_horas": 24 }
}Sincronizar stock
Es el endpoint importante. Mandá el stock completo cada pocos minutos. Es idempotente: mandar lo mismo dos veces no rompe nada. Si una cantidad llega a 0, la oferta se agota sola; si vuelve a tener, se reactiva.
curl -X POST https://superoferta.com.ar/api/v1/stock/sync \
-H "Authorization: Bearer TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "referencia": "SKU-001", "cantidad": 5 },
{ "referencia": "SKU-002", "cantidad": 0 }
]
}'La referencia es el código de TU sistema. Cargalo en la oferta (desde el panel, campo "Código de tu sistema", o al crearla por API) y con eso alcanza: no hace falta que guardes ningún id nuestro.
El latido: qué pasa si dejás de sincronizar
Cada sincronización actualiza un "último contacto". Si tu sistema se cae y pasan más horas que la tolerancia del comercio (24 por defecto), Super Oferta pausa sola las ofertas con cupo declarado y te avisa. Apenas vuelve a sincronizar, se reactivan.
Es a propósito que sea así de estricto: preferimos que pierdas una venta a que un comprador pague algo que no tenés y termine en un reclamo.
Publicar una oferta
curl -X POST https://superoferta.com.ar/api/v1/ofertas \
-H "Authorization: Bearer TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"referencia": "SKU-001",
"titulo": "Bolsa sorpresa del cierre",
"descripcion": "Facturas y pan del día, variedad según lo que quede.",
"precio_original": 9000,
"precio_oferta": 3500,
"tipo_vencimiento": "fecha",
"fecha_limite": "2026-10-05T20:30:00-03:00",
"cantidad": 12,
"condiciones": "Se retira en el local entre 19:30 y 20:30.",
"tipo_entrega": "canje",
"publicar": true
}'Si ya existe una oferta con esa referencia, se actualiza en vez de duplicarse. Sin "publicar": true queda como borrador.
Leer tus ventas
curl "https://superoferta.com.ar/api/v1/compras?desde=2026-09-01&estado=pagada" \
-H "Authorization: Bearer TU_CLAVE"Que te avisemos nosotros (webhooks)
En vez de preguntar cada minuto, dejá una dirección y te avisamos en el momento. Se configura en Panel → Integraciones → Avisos a tu sistema.
| Evento | Cuándo |
|---|---|
compra.confirmada | Alguien compró y pagó. Trae la referencia, la cantidad y el stock que queda. |
compra.cancelada | Se canceló o se devolvió: el cupo vuelve. |
voucher.canjeado | El comprador retiró. Acá la venta se concretó de verdad. |
Verificar que el aviso es nuestro
Cada aviso viaja firmado con el secreto de tu webhook, en la cabecera X-SuperOferta-Firma. Recalculala con el cuerpo crudo del pedido (no con el JSON ya parseado y vuelto a serializar, que cambia los espacios):
// Node.js
const firmaEsperada =
'sha256=' + crypto.createHmac('sha256', TU_SECRETO).update(cuerpoCrudo).digest('hex');
if (firmaEsperada !== req.headers['x-superoferta-firma']) {
return res.status(401).end(); // no vino de Super Oferta
}Respondé con 2xx. Si respondés error, reintentamos con espera creciente (1, 4, 9, 16… minutos) hasta 6 veces; después de 20 fallos seguidos, el webhook se desactiva solo y te avisamos.
Errores
Todos los errores tienen la misma forma, con el mensaje escrito para que lo lea una persona:
{ "error": { "codigo": "sin_permiso", "mensaje": "Esta clave no tiene el permiso \"stock:escribir\"." } }| Código HTTP | Qué pasó |
|---|---|
| 401 | Falta la clave o es inválida. |
| 403 | La clave existe pero no tiene ese permiso. |
| 429 | Demasiados pedidos. Mirá la cabecera Retry-After. |
| 400 | Falta un dato o vino mal. El mensaje dice cuál. |
Límites
- 120 pedidos por minuto por IP.
- Hasta 1000 items por sincronización de stock.
- Hasta 5 claves activas por comercio.
Una aclaración
Esta es la misma API que usan los sistemas propios de InHouse para publicar en Super Oferta. No hay un canal privilegiado: si el Sistema Turismo puede publicar por acá, cualquiera puede.