API e Integraciones
Documentación técnica para conectar Conexiones con tu sitio, Zapier, Slack o tu sistema interno.
1. Webhooks salientes
Conexiones envía un POST a tu URL cada vez que ocurre un evento relevante (venta, reembolso, etc). Configura suscripciones en /admin/webhooks.
Formato de la request
POST https://tu-app.com/webhook
Content-Type: application/json
User-Agent: Conexiones-Webhook/1.0
x-conexiones-event: sale.confirmed
x-conexiones-timestamp: 1716732000000
x-conexiones-signature: 6f3b1...
x-conexiones-delivery: wd_abc...
{
"event": "sale.confirmed",
"timestamp": "2026-05-26T12:00:00.000Z",
"data": {
"orderId": "CNX-MPMQ-XXXX",
"eventId": "evt_xxxxx",
"eventName": "Mi Evento",
"eventDate": "2026-06-30T22:30:00.000Z",
"customerEmail": "comprador@gmail.com",
"customerName": "Pedro Pérez",
"ticketCount": 2,
"total": 42400,
"subtotal": 40000,
"serviceFee": 2400,
"discountCode": null,
"discountAmount": 0,
"paymentMethod": "mercado-pago",
"paidAt": "2026-05-26T12:00:00.000Z"
}
}Eventos disponibles
| Evento | Cuándo se dispara |
|---|---|
| sale.confirmed | Una orden pasa a estado paid (incluye cortesías y FREE) |
| refund.created | Una orden pagada es reembolsada |
| * | Todos los eventos (suscripción por defecto) |
Verificar firma HMAC
Cada request lleva una firma en el header x-conexiones-signature. La firma se calcula como HMAC-SHA256(secret, timestamp + "." + body) en hexadecimal. El secret se genera al crear el webhook y se muestra UNA SOLA VEZ.
Ejemplo Node.js
import { createHmac, timingSafeEqual } from 'node:crypto'
function verifyConexiones(req, secret) {
const ts = req.headers['x-conexiones-timestamp']
const sig = req.headers['x-conexiones-signature']
const body = req.rawBody // necesitas el body crudo, no parseado
// Rechazar requests > 5 min para evitar replay
if (Math.abs(Date.now() - Number(ts)) > 5 * 60_000) {
throw new Error('Webhook expirado')
}
const expected = createHmac('sha256', secret)
.update(`${ts}.${body}`)
.digest('hex')
const a = Buffer.from(sig, 'hex')
const b = Buffer.from(expected, 'hex')
if (a.length !== b.length || !timingSafeEqual(a, b)) {
throw new Error('Firma inválida')
}
}Ejemplo Python
import hmac, hashlib, time
def verify_conexiones(headers, body, secret):
ts = headers['x-conexiones-timestamp']
sig = headers['x-conexiones-signature']
if abs(time.time() * 1000 - int(ts)) > 5 * 60_000:
raise ValueError('Webhook expirado')
expected = hmac.new(
secret.encode(),
f"{ts}.{body}".encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(sig, expected):
raise ValueError('Firma inválida')Reintentos y entrega
- Timeout: 5 segundos. Si tu endpoint no responde en ese tiempo, lo registramos como fallo.
- Body máximo: 16 KB. Si el payload se acerca, segmentamos.
- El servidor espera 2xx. Cualquier otro código se loguea pero no se reintenta automáticamente todavía (en roadmap).
- Cada delivery queda en la tabla
webhook_deliveriescon status + response (visible en futura UI).
2. Widget embebido
Permite vender entradas DESDE el sitio del productor sin que el comprador salga de la página.
Snippet mínimo
<button data-conexiones-evento="slug-del-evento"> Comprar entrada </button> <script src="https://www.conexiones.cloud/embed.js" defer></script>
API JS pública
// Abrir programáticamente
ConexionesEmbed.open('slug-del-evento', {
referrer: 'newsletter-marzo', // tracking opcional
})
// Cerrar
ConexionesEmbed.close()
// Versión y URL base
ConexionesEmbed.version // "1.0.0"
ConexionesEmbed.baseUrl // "https://www.conexiones.cloud"Mercado Pago en iframe
MP bloquea ser cargado dentro de iframes cross-origin (su política, no la nuestra). El widget detecta el caso y abre el form de pago de MP en una ventana nueva via window.open. Tras el pago, el comprador vuelve al sitio del productor — puede refrescar el modal o navegar al email para descargar las entradas.
Para más detalle: docs principales o ver el snippet completo en /embed-demo.html dentro del repo.
3. Estabilidad y versionado
- Campos nuevos son aditivos: podemos agregar propiedades al payload de un evento sin previo aviso. Tu integración debería ignorar propiedades desconocidas en lugar de fallar.
- Campos no se renombran: si quitamos o renombramos un campo, será con un evento nuevo (p.ej.
sale.confirmed.v2) y mantendremos el anterior por al menos 90 días. - Endpoints internos: las rutas bajo
/api/admin/*NO son API pública. No las uses desde fuera; usa el widget o los webhooks. - Sandbox: aún no exponemos un entorno de sandbox separado. Para probar webhooks puedes usar el evento Propositalk Charlas Deportivas con código
FREE— la venta se confirma sin cobro real y dispara el webhook normalmente.
¿Necesitas ayuda?
Escribe a contacto@conexiones.cloud y dime tu use case. Si lo que necesitas es razonable lo agregamos.