Recibe escaneos en tu CRM
Recibe cada escaneo en tu endpoint en el momento en que ocurre, verifícalo y guárdalo junto al contacto o la campaña a la que pertenece.
Hay dos formas de sacar los datos de escaneos: los webhooks te envían cada escaneo en menos de un segundo (Business), y GET /scans te permite traerlos por páginas cuando tú quieras (PRO y superiores). La mayoría de las integraciones con CRM usan el webhook para tener datos frescos y la consulta periódica para conciliar.
Opción A: webhooks
1. Prepara un endpoint
Una URL https en un nombre de host público que responda 2xx rápido. Haz el trabajo después de responder; las entregas tienen un tiempo de espera de diez segundos y no se reintentan.
2. Regístralo y conecta códigos
curl -X POST https://api.kuikcode.com/v1/webhooks \
-H "Authorization: Bearer kc_live_..." \
-H "Content-Type: application/json" \
-d '{ "url": "https://crm.example.com/hooks/kuikcode", "codeIds": ["K02bEPC2SmtopwPr6S-jt", "Zq9vX1mN4kLp8rTb2cWd0"] }'La respuesta incluye el id del endpoint y su secret. Existe un endpoint por URL; si vuelves a enviar la misma URL, recibes el que ya existe. PATCH /webhooks/{id} con codeIds reemplaza el conjunto conectado, así que agregar un código requiere leer, modificar y escribir.
3. Verifica cada entrega
POST /hooks/kuikcode
X-KuikCode-Event: scan.created
X-KuikCode-Delivery: 3f1c9a4e-0d5b-4c7e-9a2f-6b8d1e0c2a44
X-KuikCode-Timestamp: 1757251331
X-KuikCode-Signature: t=1757251331,v1=8c2e...
{ "event": "scan.created", "timestamp": "...", "code": { "id": "Ab3dE9xYz", "name": "Front window" },
"scan": { "scanId": "...", "country": "US", "region": "NJ", "city": "Montclair", "deviceType": "mobile",
"os": "iOS", "browser": "Safari", "language": "en", "timezone": "America/New_York",
"destination": "https://example.com/summer-menu", "matchedRule": null } }La firma es t=<unix seconds>,v1=<hex>, donde v1 es el HMAC-SHA256 de <t>.<raw body> con el secreto. Revisa que la marca de tiempo no tenga más de cinco minutos y luego compara en tiempo constante:
import { createHmac, timingSafeEqual } from "node:crypto"
export function verify(rawBody, header, secret, now = Math.floor(Date.now() / 1000)) {
const t = Number(header?.match(/(?:^|,)t=(\d+)/)?.[1])
const sig = header?.match(/(?:^|,)v1=([0-9a-f]+)/)?.[1]
if (!sig || !Number.isFinite(t) || Math.abs(now - t) > 300) return false
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex")
return sig.length === expected.length && timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
}Rechaza todo lo que falle. Cada entrega llega al menos una vez y se reintenta si falla, así que guarda X-KuikCode-Delivery y omite los valores que ya procesaste. El secreto viene en la respuesta de la creación; después, POST /webhooks/{id}/secret lo vuelve a mostrar y POST /webhooks/{id}/rotate-secret lo reemplaza con 24 horas de convivencia. Todos los detalles están en Webhooks de escaneos. code.id en el payload es el código corto impreso; relaciónalo con tu registro mediante la correspondencia que guardaste al crear los códigos.
4. Envía una prueba
POST /webhooks/{id}/test envía un evento de muestra con "test": true e informa el estado que devolvió tu servidor. Úsalo después de cada despliegue del endpoint.
Opción B: consulta con GET /scans
Para una sincronización nocturna o para recuperar datos anteriores, recorre los escaneos por páginas con una ventana de tiempo y un cursor:
curl "https://api.kuikcode.com/v1/scans?from=2026-09-01T00:00:00Z&to=2026-09-07T00:00:00Z&limit=100" \
-H "Authorization: Bearer kc_live_..."Sigue next_cursor hasta que sea null. Filtra por codeId, folderId o tag para acotar la consulta. Las ventanas se recortan al historial que incluye el plan, y la respuesta lo indica con clamped: true. Cada fila incluye los mismos campos que el payload del webhook, más la hora del escaneo.
Qué te dice un escaneo sobre una persona
Nada que la identifique. Los escaneos incluyen país, región y ciudad, dispositivo, sistema operativo, navegador e idioma, el destino que se sirvió y la regla inteligente que lo eligió. No hay dirección IP ni cookie. Para vincular un escaneo con un contacto, pon el contacto o la campaña en el propio código: un código por representante, por envío o por tienda, y parámetros UTM en el destino para tu propia analítica.
Contactos de formularios de KuikPage
Las respuestas de formularios son un flujo aparte: cada una envía form.submission a la URL del webhook del formulario con los campos identificados por sus etiquetas, y GET /submissions las lista. Consulta Webhooks de formularios.
Crea 500 códigos desde tu ERP
Convierte una lista de productos o activos en un lote de códigos diseñados, descarga los diseños y mantén el lote sincronizado.
Who am I GET
The key you are calling with, the workspace it belongs to, the plan's ceilings and current usage. The first call every integration should make.