API v1

Documentación de la API de Pokit

Integra tu punto de venta o backend con tus tarjetas de lealtad: emite tarjetas que tus clientes agregan a Apple Wallet y Google Wallet, ajusta puntos o sellos y consulta tus plantillas. Todas las respuestas son JSON y las fechas usan formato ISO 8601.

Autenticación

Genera una API key desde el panel en Ajustes → API keys. La key se muestra una sola vez; guárdala en un lugar seguro. Envíala en el header Authorization de cada solicitud. Cada key pertenece a un negocio y solo ve los datos de ese negocio.

Base URL + header de autenticación
curl "https://pokit.mx/api/v1/templates" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"

Rate limits

Cada API key admite 120 solicitudes por minuto. Al superar el límite recibirás un 429 con rate_limit_exceeded; reintenta con backoff exponencial.

Errores

Los errores devuelven un objeto JSON con un código estable en error y, cuando ayuda, un detail legible.

Formato de error
{
  "error": "validation_error",
  "detail": "customerEmail: Invalid email address"
}
CódigoerrorCuándo
401invalid_api_keyAPI key faltante, malformada o revocada.
404not_foundEl recurso no existe o no pertenece a tu negocio.
409card_revokedLa tarjeta está revocada y no acepta ajustes.
422validation_errorParámetros o body inválidos; detail explica el problema.
429rate_limit_exceededSuperaste las 120 solicitudes por minuto.

Webhooks

En vez de preguntarle a la API cada rato, deja que Pokit te avise. Configura tus URLs en Panel → Webhooks o con POST /webhooks. Cada evento sale como un POST con un cuerpo JSON y tres cabeceras: Pokit-Event (el tipo), Pokit-Delivery (el id de esa entrega) y Pokit-Signature (la firma).

Cabeceras
POST /tu/url HTTP/1.1
Content-Type: application/json
Pokit-Event: balance.earned
Pokit-Delivery: cmdlv3n8q0001pokitdlvr1
Pokit-Signature: t=1792089727,v1=6f1c0e…
Cuerpo de un evento
{
  "id": "evt_5f2c9a1e7b3d4c6f8a0b1c2d",
  "type": "balance.earned",
  "createdAt": "2026-10-15T18:42:07.120Z",
  "businessId": "cmbiz7k2p0001pokitbizn1",
  "data": {
    "card": {
      "id": "cmcrd8f2k0001pokitcard1",
      "memberNumber": "48213907",
      "customerName": "María González",
      "points": 130,
      "status": "ACTIVE"
    },
    "field": "points",
    "delta": 10,
    "balance": 130,
    "reason": "Compra en caja",
    "metadata": {
      "ticket": "A-1042"
    },
    "source": "caja",
    "branchId": null
  }
}

Eventos

Movimientos de saldo

  • balance.earned Ganó puntos o sellos
  • balance.redeemed Canjeó su recompensa
  • balance.adjusted Saldo corregido
  • balance.expired Saldo vencido

Tarjetas

  • card.created Tarjeta dada de alta
  • card.revoked Tarjeta anulada
  • card.reactivated Tarjeta reactivada
  • wallet.pass_added Agregó el pase a Wallet
  • wallet.pass_removed Quitó el pase de Wallet

Cupones

  • coupon.granted Recibió un cupón
  • coupon.redeemed Canjeó un cupón

Avisos y promociones

  • notice.sent Aviso enviado
  • promotion.started Promoción empezó
  • promotion.ended Promoción terminó

data.card es la tarjeta tal como la devuelve GET /cards/<id>. Los esquemas completos de data de cada evento están en /api/openapi.json, bajo WebhookEvent. Pide sólo los eventos que vayas a usar; webhook.test sólo sale con el botón «Enviar prueba».

Verificar la firma

Pokit-Signature tiene la forma t=<unix>,v1=<firma>. La firma es el HMAC-SHA256, en hexadecimal, de <t>.<cuerpo> usando la llave de tu URL (whsec_…). Calcúlala sobre el cuerpo crudo, tal como llegó, compárala en tiempo constante y rechaza las de más de 5 minutos para que nadie pueda repetir un evento capturado.

Node.js, sin dependencias
import { createHmac, timingSafeEqual } from "node:crypto";
import { createServer } from "node:http";

const SECRET = process.env.POKIT_WEBHOOK_SECRET; // whsec_…

function verify(body, header = "") {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = createHmac("sha256", SECRET).update(`${t}.${body}`).digest();
  const given = Buffer.from(parts.v1 ?? "", "hex");
  return given.length === expected.length && timingSafeEqual(given, expected);
}

createServer((req, res) => {
  let body = "";
  req.on("data", (chunk) => (body += chunk));
  req.on("end", () => {
    if (!verify(body, req.headers["pokit-signature"])) return res.writeHead(400).end();
    const event = JSON.parse(body);
    console.log(event.id, event.type, event.data);
    res.writeHead(200).end();
  });
}).listen(3000);

Reintentos y orden

Responde 2xx en menos de 10 segundos (procesa después si tardas). Cualquier otra respuesta, un timeout o una redirección cuentan como fallo, y Pokit reintenta a los 1 min, 5 min, 30 min, 2 h, 6 h, 12 h y 24 h; después la entrega queda failed y puedes reintentarla desde el panel o con la API. Un evento puede llegar más de una vez y no siempre en orden: usa id para no procesarlo dos veces y createdAt para ordenar.

Asistentes de IA (MCP)

Pokit expone un servidor MCP para que Claude u otro asistente trabaje con tu programa de lealtad hablándole: «programa un 2×1 todos los lunes de 1 a 5 y avisa a mis clientes», «avísale a Laura que su pedido está listo». Hay dos formas de conectarlo; las dos usan la misma dirección y el mismo límite de solicitudes.

Dirección del servidor (transporte Streamable HTTP): https://pokit.mx/api/mcp

Con tu cuenta (OAuth) — sólo la URL

Pega la dirección en tu asistente (Claude, Cursor…). Se abre Pokit en el navegador, inicias sesión —con tu verificación en dos pasos, si la tienes— y autorizas la aplicación para tu negocio. No hay ninguna key que copiar. Sólo el dueño del negocio puede autorizar, y puedes quitar el acceso al instante en API Keys → Aplicaciones conectadas.

claude mcp add --transport http pokit https://pokit.mx/api/mcp

Con una API key — cabecera

Para scripts, servidores y clientes sin navegador: envía la misma key de la API REST en la cabecera Authorization.

claude mcp add --transport http pokit https://pokit.mx/api/mcp \
  --header "Authorization: Bearer pk_live_xxxxxxxxxxxx"
  • get_business Datos del negocio: nombre, zona horaria (en la que se leen los horarios de las promociones) y sus plantillas de tarjeta con tipo (POINTS, STAMPS o MEMBERSHIP), recompensa y reglas.
  • search_cards Busca tarjetas de clientes por nombre, correo, teléfono o número de serie (lo que trae el código del pase).
  • get_card Una tarjeta con su saldo, sus enlaces, sus cupones (status: redeemable, off_hours, exhausted o expired) y sus últimos movimientos y avisos.
  • verify_code Identifica a un cliente por lo que enseña en caja y dice si su código rotativo es vigente, sin mover saldo.
  • adjust_balance Suma (delta positivo) o resta (delta negativo) puntos o sellos a una tarjeta.
  • redeem_reward Canjea la recompensa de una tarjeta: en sellos consume la tarjeta llena; en puntos, la cantidad indicada en `amount`.
  • send_notice Manda un aviso a la pantalla de bloqueo del cliente a través de su pase, p.
  • broadcast_notice Manda el mismo aviso a la pantalla de bloqueo de VARIOS clientes: a tarjetas concretas (`cardIds`), a todas las de una plantilla (`templateId`) o a todo el negocio (`all: true`).
  • list_promotions Las promociones del negocio: cuáles están en vivo, su horario y qué cambian en el pase.
  • create_promotion Crea una promoción que cambia temporalmente los pases: un texto visible (`text`), colores, y opcionalmente un aviso en pantalla de bloqueo (`notify` + `message`).
  • set_promotion_enabled Enciende o apaga una promoción.
  • delete_promotion Elimina una promoción.
  • list_coupons Los cupones del negocio: qué ofrecen, a quién se le dan (audience), sus límites, cuántas veces se han canjeado y su estado (active, scheduled, expired, exhausted u off).
  • create_coupon Crea un cupón que aparece dentro de la tarjeta del cliente (pase y página).
  • set_coupon_enabled Enciende o apaga un cupón.
  • grant_coupon Le da a una tarjeta un cupón de audiencia 'selected'.
  • redeem_coupon Marca un cupón como usado por una tarjeta (el beneficio lo aplica quien atiende).
  • list_branches Lista las sucursales del negocio (id, nombre, dirección, coordenadas, mensaje de pantalla de bloqueo y si está activa).
  • search_customers Busca perfiles de clientes por nombre, correo, teléfono o número de socio.
  • get_customer Perfil completo de un cliente: datos de contacto, todas sus tarjetas con su saldo y métricas (visitas, última visita, visitas al mes en los últimos 90 días, sucursal favorita, cupones canjeados y ticket promedio si la caja manda `total` en metadata).
  • list_webhooks Las URLs de webhook del negocio: a dónde se envían los eventos, cuáles recibe cada una y si están activas.
  • list_webhook_deliveries Bitácora de entregas de webhooks (30 días): qué evento salió, a qué URL, si llegó (delivered), sigue reintentando (pending) o falló (failed), con el código HTTP y el error.

Lo que haga el asistente llega al teléfono de clientes reales y queda en la bitácora de Auditoría.

¿Usas un asistente de IA? Dale /llms-full.txt (referencia completa en Markdown, siempre al día).

Plantillas

GET /templates

Listar plantillas

Devuelve las plantillas de tarjeta de tu negocio con el número de tarjetas emitidas por cada una.

Ejemplo · curl
curl "https://pokit.mx/api/v1/templates" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Lista de plantillas.
[
  {
    "id": "cmtpl1a2b0003pokittmpl1",
    "name": "Café Aroma — Puntos",
    "type": "POINTS",
    "active": true,
    "createdAt": "2026-05-12T10:00:00.000Z",
    "cards": 342
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /templates/{id}

Detalle de plantilla

Devuelve una plantilla con su diseño, reglas y sucursales. `branches` son las sucursales activas donde vale (todas las del negocio si no se eligieron) en el orden de la plantilla; `branchPass` dice cuáles 10 llegan al pase: `fixed` (las primeras 10) o `nearest` (las 10 más cercanas a la última sucursal donde se movió cada tarjeta).

Parámetros

NombreEnTipoDescripción
id*pathstringID de la plantilla.
Ejemplo · curl
curl "https://pokit.mx/api/v1/templates/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Plantilla con sus sucursales.
{
  "id": "cmtpl1a2b0003pokittmpl1",
  "name": "Café Aroma — Puntos",
  "type": "POINTS",
  "description": "Acumula puntos por cada compra.",
  "backgroundColor": "#1a1a2e",
  "foregroundColor": "#ffffff",
  "labelColor": "#a0a0c0",
  "logoText": "Café Aroma",
  "stripImageUrl": null,
  "stampsTotal": 10,
  "pointsPerVisit": 10,
  "rewardText": "Café gratis a los 100 puntos",
  "barcodeFormat": "QR",
  "active": true,
  "createdAt": "2026-05-12T10:00:00.000Z",
  "updatedAt": "2026-06-01T08:00:00.000Z",
  "branchPass": "nearest",
  "branches": [
    {
      "id": "cmbrc4k9p0007pokitbrc01",
      "name": "Okuma Polanco",
      "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
      "latitude": 19.4326,
      "longitude": -99.1937,
      "relevantText": "¡Estás cerca de Okuma Polanco! Muestra tu tarjeta.",
      "active": true,
      "createdAt": "2026-09-02T16:20:00.000Z"
    }
  ],
  "locations": [
    {
      "id": "cmbrc4k9p0007pokitbrc01",
      "templateId": "cmtpl1a2b0003pokittmpl1",
      "name": "Sucursal Centro",
      "latitude": 19.4326,
      "longitude": -99.1332,
      "relevantText": "¡Estás cerca de Café Aroma! Muestra tu tarjeta."
    }
  ],
  "cards": 342
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.

Tarjetas

GET /cards

Listar tarjetas

Lista paginada de tarjetas del negocio. Filtra por plantilla, email, teléfono, serial o número de socio. Para identificar a quien escanea su pass en caja, busca por `serial`: es el valor del código. Si la plantilla usa código rotativo, lo que se escanea son 14 dígitos: usa `POST /codes/verify`.

Parámetros

NombreEnTipoDescripción
templateIdquerystringFiltra por plantilla.
emailquerystringFiltra por email exacto del cliente.
phonequerystringFiltra por teléfono exacto del cliente (10 a 15 dígitos).
serialquerystringFiltra por serial: el valor que contiene el código QR o de barras del pass.
memberNumberquerystringFiltra por número de socio: los 8 dígitos fijos con los que empieza el código de la tarjeta.
pagequeryintegerPágina (desde 1).
limitqueryintegerResultados por página (máx. 100).
Ejemplo · curl
curl "https://pokit.mx/api/v1/cards" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Página de tarjetas.
{
  "data": [
    {
      "id": "cmcrd8f2k0001pokitcard1",
      "serial": "cmsrl4x9m0002pokitserl1",
      "memberNumber": "48213907",
      "templateId": "cmtpl1a2b0003pokittmpl1",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {
        "tu_cumpleanos": "1990-05-14"
      },
      "points": 120,
      "stamps": 0,
      "status": "ACTIVE",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-07-18T09:12:00.000Z"
    }
  ],
  "page": 1,
  "limit": 20,
  "total": 342
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /cards

Emitir tarjeta

Crea una tarjeta para un cliente a partir de una plantilla de tu negocio; la respuesta incluye las URLs para compartirla y agregarla al wallet. Hay una sola tarjeta por correo y plantilla: si ya existe, responde 200 con la tarjeta existente en vez de duplicarla, así que reintentar tras un fallo de red es seguro. El correo se guarda en minúsculas. El cuerpo debe ir como JSON con `Content-Type: application/json` (si no, 400 o 415).

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/cards" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "templateId": "cmtpl1a2b0003pokittmpl1",
  "customerName": "María González",
  "customerEmail": "maria@ejemplo.com"
}'
Request body
{
  "templateId": "cmtpl1a2b0003pokittmpl1",
  "customerName": "María González",
  "customerEmail": "maria@ejemplo.com"
}
Respuesta 201 · Tarjeta creada.
{
  "id": "cmcrd8f2k0001pokitcard1",
  "serial": "cmsrl4x9m0002pokitserl1",
  "memberNumber": "48213907",
  "templateId": "cmtpl1a2b0003pokittmpl1",
  "customerId": "cmcus3k8p0005pokitcust1",
  "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
  "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
  "customerName": "María González",
  "customerEmail": "maria@ejemplo.com",
  "customerPhone": "5512345678",
  "data": {
    "tu_cumpleanos": "1990-05-14"
  },
  "points": 0,
  "stamps": 0,
  "status": "ACTIVE",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z",
  "urls": {
    "public": "https://pokit.mx/c/cmcrd8f2k0001pokitcard1",
    "appleWallet": "https://pokit.mx/api/wallet/apple/cmcrd8f2k0001pokitcard1",
    "googleWallet": "https://pokit.mx/api/wallet/google/cmcrd8f2k0001pokitcard1"
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 La plantilla no existe o no pertenece a tu negocio.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /cards/{id}

Detalle de tarjeta

Devuelve una tarjeta con sus URLs públicas y de wallet.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl "https://pokit.mx/api/v1/cards/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Tarjeta.
{
  "id": "cmcrd8f2k0001pokitcard1",
  "serial": "cmsrl4x9m0002pokitserl1",
  "memberNumber": "48213907",
  "templateId": "cmtpl1a2b0003pokittmpl1",
  "customerId": "cmcus3k8p0005pokitcust1",
  "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
  "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
  "customerName": "María González",
  "customerEmail": "maria@ejemplo.com",
  "customerPhone": "5512345678",
  "data": {
    "tu_cumpleanos": "1990-05-14"
  },
  "points": 120,
  "stamps": 0,
  "status": "ACTIVE",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z",
  "urls": {
    "public": "https://pokit.mx/c/cmcrd8f2k0001pokitcard1",
    "appleWallet": "https://pokit.mx/api/wallet/apple/cmcrd8f2k0001pokitcard1",
    "googleWallet": "https://pokit.mx/api/wallet/google/cmcrd8f2k0001pokitcard1"
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
DELETE /cards/{id}

Revocar tarjeta

Revoca una tarjeta (status `REVOKED`). Una tarjeta revocada ya no acepta ajustes de puntos o sellos.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl -X DELETE "https://pokit.mx/api/v1/cards/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Tarjeta revocada.
{
  "id": "cmcrd8f2k0001pokitcard1",
  "status": "REVOKED"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /cards/{id}/points

Ajustar puntos o sellos

Suma o resta puntos (o sellos) a una tarjeta. `delta` puede ser negativo; el saldo nunca baja de 0 y los sellos nunca pasan del total de la plantilla. Manda `reason` y `metadata` para dejar trazabilidad: quedan en el historial de la tarjeta. El pass del cliente se actualiza solo en su wallet, con una notificación del saldo nuevo.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/cards/{id}/points" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "delta": 10,
  "field": "points",
  "reason": "Compra en sucursal Centro",
  "metadata": {
    "ticket": "A-10482",
    "total": 349.5,
    "cajero": "Ana"
  },
  "branchId": "cmbrc4k9p0007pokitbrc01"
}'
Request body
{
  "delta": 10,
  "field": "points",
  "reason": "Compra en sucursal Centro",
  "metadata": {
    "ticket": "A-10482",
    "total": 349.5,
    "cajero": "Ana"
  },
  "branchId": "cmbrc4k9p0007pokitbrc01"
}
Respuesta 200 · Tarjeta con el saldo actualizado.
{
  "id": "cmcrd8f2k0001pokitcard1",
  "serial": "cmsrl4x9m0002pokitserl1",
  "memberNumber": "48213907",
  "templateId": "cmtpl1a2b0003pokittmpl1",
  "customerId": "cmcus3k8p0005pokitcust1",
  "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
  "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
  "customerName": "María González",
  "customerEmail": "maria@ejemplo.com",
  "customerPhone": "5512345678",
  "data": {
    "tu_cumpleanos": "1990-05-14"
  },
  "points": 130,
  "stamps": 0,
  "status": "ACTIVE",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 409 La tarjeta está revocada (`card_revoked`) o la tarjeta de sellos ya está completa (`stamps_full`). Si la plantilla exige el código rotativo: falta `code` (`code_required`), no es de esta tarjeta (`code_invalid`), ya venció (`code_expired`) o ya se usó en otro canje (`code_reused`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /cards/{id}/redeem

Canjear recompensa

Canjea la recompensa de una tarjeta. En tarjetas de sellos consume la tarjeta completa y exige que esté llena; en tarjetas de puntos consume `amount`. El canje cuenta como visita para el vencimiento por inactividad.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/cards/{id}/redeem" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 500,
  "reason": "Canje: $100 de descuento",
  "metadata": {
    "ticket": "A-10511"
  }
}'
Request body
{
  "amount": 500,
  "reason": "Canje: $100 de descuento",
  "metadata": {
    "ticket": "A-10511"
  }
}
Respuesta 200 · Tarjeta con el saldo tras el canje.
{
  "id": "cmcrd8f2k0001pokitcard1",
  "serial": "cmsrl4x9m0002pokitserl1",
  "memberNumber": "48213907",
  "templateId": "cmtpl1a2b0003pokittmpl1",
  "customerId": "cmcus3k8p0005pokitcust1",
  "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
  "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
  "customerName": "María González",
  "customerEmail": "maria@ejemplo.com",
  "customerPhone": "5512345678",
  "data": {
    "tu_cumpleanos": "1990-05-14"
  },
  "points": 20,
  "stamps": 0,
  "status": "ACTIVE",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 409 El saldo no alcanza (`insufficient_balance`), la tarjeta está revocada (`card_revoked`) o es de membresía (`nothing_to_redeem`). Si la plantilla exige el código rotativo: falta `code` (`code_required`), no es de esta tarjeta (`code_invalid`), ya venció (`code_expired`) o ya se usó en otro canje (`code_reused`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /notices

Enviar aviso a varios clientes

Manda el mismo aviso a la pantalla de bloqueo de varios clientes. Indica exactamente un destino: `cardIds` (hasta 500 tarjetas), `templateId` (todas las tarjetas activas de esa plantilla) o `all: true` (todas las del negocio). Las tarjetas revocadas se saltan. Máximo 6 envíos a varias tarjetas por hora.

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/notices" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "message": "Hoy cerramos a las 6 pm por evento privado",
  "all": true
}'
Request body
{
  "message": "Hoy cerramos a las 6 pm por evento privado",
  "all": true
}
Respuesta 200 · Aviso enviado; `sent` es a cuántas tarjetas llegó.
{
  "sent": 124,
  "androidSilent": 2
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 Ninguna tarjeta activa coincide con el destino (`no_recipients`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /cards/{id}/notify

Enviar aviso al cliente

Manda un aviso a la pantalla de bloqueo del cliente a través de su pase en Wallet: «Tu pedido #45 está listo». No mueve saldo. `status` y `orderId` son opcionales y quedan en el historial de la tarjeta (`kind: notice`). Máximo 20 avisos por tarjeta por hora. Si repites exactamente el mismo mensaje, se le añade la hora para que Wallet lo vuelva a notificar.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/cards/{id}/notify" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "message": "Tu pedido #45 está listo",
  "status": "listo",
  "orderId": "45"
}'
Request body
{
  "message": "Tu pedido #45 está listo",
  "status": "listo",
  "orderId": "45"
}
Respuesta 200 · Aviso registrado y enviado al pase.
{
  "cardId": "tz4a98xxat96iws9zmbrgj3a",
  "notice": "Tu pedido #45 está listo",
  "sentAt": "2026-10-07T19:02:11.000Z",
  "androidSilent": false
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 409 La tarjeta está revocada (`card_revoked`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /cards/{id}/events

Historial de movimientos

Cada suma, canje, corrección, vencimiento, aviso o cupón canjeado de la tarjeta, del más reciente al más antiguo, con su motivo y metadata.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
limitqueryintegerMáximo de movimientos (1 a 200).
Ejemplo · curl
curl "https://pokit.mx/api/v1/cards/{id}/events" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Movimientos de la tarjeta.
{
  "data": [
    {
      "id": "cmevt7h3q0009pokitevt1",
      "field": "points",
      "kind": "earn",
      "delta": 10,
      "balanceAfter": 130,
      "reason": "Compra en sucursal Centro",
      "metadata": {
        "ticket": "A-10482"
      },
      "source": "api",
      "createdAt": "2026-07-18T09:12:00.000Z"
    }
  ]
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.

Código rotativo

POST /codes/verify

Verificar un código

Identifica al cliente por lo que enseñó en caja y dice si su código es vigente, sin mover saldo ni gastar el código. `code` acepta los 14 dígitos del código rotativo (identifica y verifica), los 8 del número de socio, el serial del pase o la URL de la tarjeta (sólo identifican). El código de la tarjeta en línea cambia cada 30 segundos y se acepta una ventana de tolerancia; el del pase de Wallet cambia cada 1, 6 o 24 horas y se aceptan la ventana actual y la anterior. Máximo 8 intentos por tarjeta cada 10 minutos.

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/codes/verify" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "4821 3907 · 512 904"
}'
Request body
{
  "code": "4821 3907 · 512 904"
}
Respuesta 200 · Cliente identificado. `verified` dice si el código es vigente.
{
  "card": {
    "id": "cmcrd8f2k0001pokitcard1",
    "serial": "cmsrl4x9m0002pokitserl1",
    "memberNumber": "48213907",
    "templateId": "cmtpl1a2b0003pokittmpl1",
    "customerId": "cmcus3k8p0005pokitcust1",
    "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
    "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
    "customerName": "María González",
    "customerEmail": "maria@ejemplo.com",
    "customerPhone": "5512345678",
    "data": {
      "tu_cumpleanos": "1990-05-14"
    },
    "points": 120,
    "stamps": 0,
    "status": "ACTIVE",
    "createdAt": "2026-07-01T15:30:00.000Z",
    "updatedAt": "2026-07-18T09:12:00.000Z"
  },
  "verified": true,
  "source": "page",
  "expiresInSeconds": 41,
  "reason": null
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 Ese código, número de socio, serial o URL no es de una tarjeta de tu negocio.
  • 409 Sólo si la plantilla EXIGE el código para validar al cliente: no llegó un código completo (`code_required`), no es de esa tarjeta (`code_invalid`), ya venció (`code_expired`) o ya se usó en un canje (`code_reused`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /cards/{id}/code

Código vigente de una tarjeta

Devuelve el código rotativo vigente de la tarjeta en línea y cuántos segundos le quedan, para integraciones que pintan su propia pantalla del cliente. Pídelo de nuevo cuando venza (cada 30 segundos): no lo guardes. El secreto con el que se calcula nunca sale de Pokit.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl "https://pokit.mx/api/v1/cards/{id}/code" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · El código vigente.
{
  "cardId": "cmcrd8f2k0001pokitcard1",
  "memberNumber": "48213907",
  "code": "48213907512904",
  "formatted": "4821 3907 · 512 904",
  "expiresInSeconds": 23
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 409 La plantilla de la tarjeta no tiene el código rotativo encendido (`code_not_enabled`) o la tarjeta está revocada (`card_revoked`).
  • 429 Límite de 120 solicitudes por minuto excedido.

Promociones

GET /promotions

Listar promociones

Las promociones de tu negocio, de la más reciente a la más antigua. `live` dice si está aplicada ahora mismo en los pases; `when` resume su horario en una frase.

Ejemplo · curl
curl "https://pokit.mx/api/v1/promotions" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Lista de promociones.
[
  {
    "id": "cmprm3k8d0005pokitprom1",
    "name": "Miércoles de 2×1",
    "enabled": true,
    "live": false,
    "when": "Cada miércoles de 13:00 a 17:00",
    "schedule": {
      "mode": "weekly",
      "days": [
        3
      ],
      "from": "13:00",
      "to": "17:00",
      "until": null
    },
    "text": "2×1 en rollos toda la tarde",
    "message": "Hoy 2×1 en rollos, de 1 a 5 de la tarde",
    "notify": "first",
    "templateIds": [],
    "backgroundColor": null,
    "foregroundColor": null,
    "labelColor": null,
    "hasPhoto": false,
    "createdAt": "2026-10-01T16:00:00.000Z",
    "updatedAt": "2026-10-01T16:00:00.000Z"
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /promotions

Crear promoción

Crea una promoción que cambia temporalmente los pases: un texto en el frente (`text`), los colores y, si quieres, un aviso en la pantalla de bloqueo (`notify` + `message`). `schedule` decide cuándo está en vivo; las horas se leen en la zona horaria del negocio. Debe cambiar algo: `text`, `message` o colores. La foto de la promoción sólo se sube desde el panel.

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/promotions" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Miércoles de 2×1",
  "text": "2×1 en rollos toda la tarde",
  "message": "Hoy 2×1 en rollos, de 1 a 5 de la tarde",
  "notify": "first",
  "schedule": {
    "mode": "weekly",
    "days": [
      3
    ],
    "from": "13:00",
    "to": "17:00"
  }
}'
Request body
{
  "name": "Miércoles de 2×1",
  "text": "2×1 en rollos toda la tarde",
  "message": "Hoy 2×1 en rollos, de 1 a 5 de la tarde",
  "notify": "first",
  "schedule": {
    "mode": "weekly",
    "days": [
      3
    ],
    "from": "13:00",
    "to": "17:00"
  }
}
Respuesta 201 · Promoción creada.
{
  "id": "cmprm3k8d0005pokitprom1",
  "name": "Miércoles de 2×1",
  "enabled": true,
  "live": false,
  "when": "Cada miércoles de 13:00 a 17:00",
  "schedule": {
    "mode": "weekly",
    "days": [
      3
    ],
    "from": "13:00",
    "to": "17:00",
    "until": null
  },
  "text": "2×1 en rollos toda la tarde",
  "message": "Hoy 2×1 en rollos, de 1 a 5 de la tarde",
  "notify": "first",
  "templateIds": [],
  "backgroundColor": null,
  "foregroundColor": null,
  "labelColor": null,
  "hasPhoto": false,
  "createdAt": "2026-10-01T16:00:00.000Z",
  "updatedAt": "2026-10-01T16:00:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 422 Body inválido, `templateIds` con una plantilla ajena, o una promoción que no cambia nada.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /promotions/{id}

Obtener promoción

Parámetros

NombreEnTipoDescripción
id*pathstringID de la promoción.
Ejemplo · curl
curl "https://pokit.mx/api/v1/promotions/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · La promoción.
{
  "id": "cmprm3k8d0005pokitprom1",
  "name": "Miércoles de 2×1",
  "enabled": true,
  "live": false,
  "when": "Cada miércoles de 13:00 a 17:00",
  "schedule": {
    "mode": "weekly",
    "days": [
      3
    ],
    "from": "13:00",
    "to": "17:00",
    "until": null
  },
  "text": "2×1 en rollos toda la tarde",
  "message": "Hoy 2×1 en rollos, de 1 a 5 de la tarde",
  "notify": "first",
  "templateIds": [],
  "backgroundColor": null,
  "foregroundColor": null,
  "labelColor": null,
  "hasPhoto": false,
  "createdAt": "2026-10-01T16:00:00.000Z",
  "updatedAt": "2026-10-01T16:00:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
PATCH /promotions/{id}

Editar promoción

Cambia sólo los campos enviados; el resultado se valida completo. Sirve para encender o apagar (`enabled`), mover el horario o cambiar el texto. Si la promoción está en vivo, los pases se actualizan de inmediato.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la promoción.
Ejemplo · curl
curl -X PATCH "https://pokit.mx/api/v1/promotions/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": false
}'
Request body
{
  "enabled": false
}
Respuesta 200 · Promoción actualizada.
{
  "id": "cmprm3k8d0005pokitprom1",
  "name": "Miércoles de 2×1",
  "enabled": false,
  "live": false,
  "when": "Cada miércoles de 13:00 a 17:00",
  "schedule": {
    "mode": "weekly",
    "days": [
      3
    ],
    "from": "13:00",
    "to": "17:00",
    "until": null
  },
  "text": "2×1 en rollos toda la tarde",
  "message": "Hoy 2×1 en rollos, de 1 a 5 de la tarde",
  "notify": "first",
  "templateIds": [],
  "backgroundColor": null,
  "foregroundColor": null,
  "labelColor": null,
  "hasPhoto": false,
  "createdAt": "2026-10-01T16:00:00.000Z",
  "updatedAt": "2026-10-01T16:00:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
DELETE /promotions/{id}

Eliminar promoción

Si estaba en vivo, los pases vuelven a su diseño normal.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la promoción.
Ejemplo · curl
curl -X DELETE "https://pokit.mx/api/v1/promotions/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.

Cupones

GET /coupons

Listar cupones

Los cupones de tu negocio con sus canjes (`redemptions`) y su estado: `active`, `scheduled` (aún no empieza), `expired`, `exhausted` (se acabaron los usos totales) u `off` (apagado).

Ejemplo · curl
curl "https://pokit.mx/api/v1/coupons" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Lista de cupones.
[
  {
    "id": "cmcpn9v2r0006pokitcpn01",
    "name": "Postre gratis",
    "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
    "enabled": true,
    "status": "active",
    "summary": "Para todos los clientes · 1 uso por cliente · 100 en total",
    "audience": "all",
    "validDays": 30,
    "templateIds": [],
    "startsAt": "2026-10-01",
    "endsAt": "2026-10-31",
    "hours": {
      "days": [
        1,
        2,
        3,
        4,
        5
      ],
      "from": "13:00",
      "to": "17:00"
    },
    "maxPerCustomer": 1,
    "maxTotal": 100,
    "notify": true,
    "redemptions": 12,
    "createdAt": "2026-10-01T16:00:00.000Z",
    "updatedAt": "2026-10-01T16:00:00.000Z"
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /coupons

Crear cupón

Un cupón es un beneficio en texto («Postre gratis») que aparece dentro de la tarjeta del cliente: en su pase de Wallet y en su página. Al canjearlo sólo se marca como usado; el beneficio lo aplica quien atiende. `audience` decide quién lo recibe: `all` (todas las tarjetas), `selected` (a quien se lo des con `/coupons/{id}/grant`), `welcome` (clientes nuevos, `validDays` días desde el alta) o `birthday` (`validDays` días desde el cumpleaños, cada año; requiere una pregunta de cumpleaños en el formulario de alta). Todos los límites son opcionales. Con `notify: true` el cliente recibe un aviso en su pantalla de bloqueo al recibirlo (no aplica a `welcome`).

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/coupons" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Postre gratis",
  "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
  "audience": "all",
  "startsAt": "2026-10-01",
  "endsAt": "2026-10-31",
  "hours": {
    "days": [
      1,
      2,
      3,
      4,
      5
    ],
    "from": "13:00",
    "to": "17:00"
  },
  "maxPerCustomer": 1,
  "maxTotal": 100,
  "notify": true
}'
Request body
{
  "name": "Postre gratis",
  "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
  "audience": "all",
  "startsAt": "2026-10-01",
  "endsAt": "2026-10-31",
  "hours": {
    "days": [
      1,
      2,
      3,
      4,
      5
    ],
    "from": "13:00",
    "to": "17:00"
  },
  "maxPerCustomer": 1,
  "maxTotal": 100,
  "notify": true
}
Respuesta 201 · Cupón creado.
{
  "id": "cmcpn9v2r0006pokitcpn01",
  "name": "Postre gratis",
  "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
  "enabled": true,
  "status": "active",
  "summary": "Para todos los clientes · 1 uso por cliente · 100 en total",
  "audience": "all",
  "validDays": 30,
  "templateIds": [],
  "startsAt": "2026-10-01",
  "endsAt": "2026-10-31",
  "hours": {
    "days": [
      1,
      2,
      3,
      4,
      5
    ],
    "from": "13:00",
    "to": "17:00"
  },
  "maxPerCustomer": 1,
  "maxTotal": 100,
  "notify": true,
  "redemptions": 0,
  "createdAt": "2026-10-01T16:00:00.000Z",
  "updatedAt": "2026-10-01T16:00:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 422 Body inválido o `templateIds` con una plantilla ajena.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /coupons/{id}

Obtener cupón

Parámetros

NombreEnTipoDescripción
id*pathstringID del cupón.
Ejemplo · curl
curl "https://pokit.mx/api/v1/coupons/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · El cupón.
{
  "id": "cmcpn9v2r0006pokitcpn01",
  "name": "Postre gratis",
  "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
  "enabled": true,
  "status": "active",
  "summary": "Para todos los clientes · 1 uso por cliente · 100 en total",
  "audience": "all",
  "validDays": 30,
  "templateIds": [],
  "startsAt": "2026-10-01",
  "endsAt": "2026-10-31",
  "hours": {
    "days": [
      1,
      2,
      3,
      4,
      5
    ],
    "from": "13:00",
    "to": "17:00"
  },
  "maxPerCustomer": 1,
  "maxTotal": 100,
  "notify": true,
  "redemptions": 12,
  "createdAt": "2026-10-01T16:00:00.000Z",
  "updatedAt": "2026-10-01T16:00:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
PATCH /coupons/{id}

Editar cupón

Cambia sólo los campos enviados; el resultado se valida completo. Los pases afectados se actualizan de inmediato. Para quitar un límite manda `null` (p. ej. `{ "maxTotal": null }`).

Parámetros

NombreEnTipoDescripción
id*pathstringID del cupón.
Ejemplo · curl
curl -X PATCH "https://pokit.mx/api/v1/coupons/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "endsAt": "2026-11-15",
  "maxTotal": 200
}'
Request body
{
  "endsAt": "2026-11-15",
  "maxTotal": 200
}
Respuesta 200 · Cupón actualizado.
{
  "id": "cmcpn9v2r0006pokitcpn01",
  "name": "Postre gratis",
  "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
  "enabled": true,
  "status": "active",
  "summary": "Para todos los clientes · 1 uso por cliente · 200 en total",
  "audience": "all",
  "validDays": 30,
  "templateIds": [],
  "startsAt": "2026-10-01",
  "endsAt": "2026-11-15",
  "hours": {
    "days": [
      1,
      2,
      3,
      4,
      5
    ],
    "from": "13:00",
    "to": "17:00"
  },
  "maxPerCustomer": 1,
  "maxTotal": 200,
  "notify": true,
  "redemptions": 12,
  "createdAt": "2026-10-01T16:00:00.000Z",
  "updatedAt": "2026-10-01T16:00:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
DELETE /coupons/{id}

Eliminar cupón

Desaparece de los pases. Se eliminan sus otorgamientos y canjes; el historial de cada tarjeta conserva los suyos.

Parámetros

NombreEnTipoDescripción
id*pathstringID del cupón.
Ejemplo · curl
curl -X DELETE "https://pokit.mx/api/v1/coupons/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /coupons/{id}/grant

Dar un cupón a una tarjeta

Le da a una tarjeta un cupón de audiencia `selected`. Si el cupón tiene `notify`, el cliente recibe el aviso «Tienes un cupón: …». Es idempotente: si ya lo tenía responde `created: false` y no vuelve a avisar.

Parámetros

NombreEnTipoDescripción
id*pathstringID del cupón.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/coupons/{id}/grant" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "cardId": "cmcrd8f2k0001pokitcard1"
}'
Request body
{
  "cardId": "cmcrd8f2k0001pokitcard1"
}
Respuesta 200 · Cupón otorgado (o ya lo tenía).
{
  "couponId": "cmcpn9v2r0006pokitcpn01",
  "cardId": "cmcrd8f2k0001pokitcard1",
  "name": "Postre gratis",
  "created": true
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El cupón o la tarjeta no existen o no pertenecen a tu negocio.
  • 409 El cupón no es `selected` (`coupon_not_grantable`), no le sirve a esa tarjeta porque está apagado, vencido, agotado o es de otra plantilla (`coupon_not_available`), o la tarjeta está revocada (`card_revoked`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /cards/{id}/coupons

Cupones de una tarjeta

Los cupones que tiene este cliente ahora mismo, con su estado: `redeemable` (se puede canjear ya), `off_hours` (lo tiene, pero no es su día u hora), `exhausted` (ya lo usó o se agotó) o `expired`. Los que no le corresponden no aparecen. `validity` es el texto de vigencia que ve el cliente.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
Ejemplo · curl
curl "https://pokit.mx/api/v1/cards/{id}/coupons" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Cupones de la tarjeta.
[
  {
    "id": "cmcpn9v2r0006pokitcpn01",
    "name": "Postre gratis",
    "description": "En consumo mínimo de $200. No acumulable con otras promociones.",
    "audience": "all",
    "status": "redeemable",
    "validity": "Cada lunes, martes, miércoles, jueves y viernes de 13:00 a 17:00 · Hasta el 31 oct",
    "used": 0,
    "maxPerCustomer": 1
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /cards/{id}/coupons/{couponId}/redeem

Canjear un cupón

Marca el cupón como usado por esta tarjeta. No se puede deshacer. El cuerpo es opcional: sólo lleva `code` (el código rotativo que enseñó el cliente) si la plantilla lo pide. Queda en el historial de la tarjeta (`kind: coupon`) y el cupón desaparece de su pase cuando llega a su límite. Dos canjes simultáneos nunca se saltan `maxPerCustomer` ni `maxTotal`.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la tarjeta.
couponId*pathstringID del cupón.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/cards/{id}/coupons/{couponId}/redeem" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "48213907512904",
  "branchId": "cmbrc4k9p0007pokitbrc01"
}'
Request body
{
  "code": "48213907512904",
  "branchId": "cmbrc4k9p0007pokitbrc01"
}
Respuesta 200 · Cupón canjeado.
{
  "couponId": "cmcpn9v2r0006pokitcpn01",
  "cardId": "cmcrd8f2k0001pokitcard1",
  "name": "Postre gratis",
  "redeemedAt": "2026-10-07T19:02:11.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 409 El cupón no se puede canjear: la tarjeta no lo tiene (`coupon_not_available`), ya se usó (`coupon_exhausted`), venció (`coupon_expired`), no es su horario (`coupon_off_hours`) o la tarjeta está revocada (`card_revoked`). Si la plantilla exige el código rotativo: falta `code` (`code_required`), no es de esta tarjeta (`code_invalid`), ya venció (`code_expired`) o ya se usó en otro canje (`code_reused`).
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.

Webhooks

GET /webhooks

Listar URLs de webhook

Las URLs a las que Pokit envía eventos de tu negocio, con los eventos que recibe cada una. No incluye el `secret`: pídelo con `GET /webhooks/{id}`.

Ejemplo · curl
curl "https://pokit.mx/api/v1/webhooks" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Lista de URLs.
[
  {
    "id": "cmwhk2b7c0001pokitwhk01",
    "url": "https://pos.cafearoma.mx/webhooks/pokit",
    "description": "Punto de venta de Sucursal Centro",
    "events": [
      "balance.earned",
      "balance.redeemed",
      "card.created"
    ],
    "enabled": true,
    "createdAt": "2026-10-15T16:20:00.000Z",
    "updatedAt": "2026-10-15T16:20:00.000Z"
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /webhooks

Crear URL de webhook

Registra una URL que recibirá un POST por cada evento elegido en `events`. La URL debe ser `https://` y pública: se rechazan las que resuelven a redes privadas, loopback, link-local o metadatos de la nube. La respuesta trae el `secret` (`whsec_…`) con el que se firma cada envío. **Firma.** Cada envío lleva `Pokit-Signature: t=<unix>,v1=<firma>`, donde la firma es el HMAC-SHA256 en hexadecimal de `<t>.<cuerpo crudo>` con el `secret`. Verifícala comparando en tiempo constante y rechaza las de más de 5 minutos. También llegan `Pokit-Event` (el tipo) y `Pokit-Delivery` (el id de la entrega). **Entrega.** Responde 2xx en menos de 10 s. Cualquier otra respuesta, un timeout o una redirección (no se siguen) es un fallo y se reintenta a los 1 min, 5 min, 30 min, 2 h, 6 h, 12 h y 24 h; luego la entrega queda `failed`. Un evento puede llegar más de una vez: usa su `id` para descartar repetidos. Máximo 10 URLs por negocio.

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/webhooks" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://pos.cafearoma.mx/webhooks/pokit",
  "description": "Punto de venta de Sucursal Centro",
  "events": [
    "balance.earned",
    "balance.redeemed",
    "card.created"
  ]
}'
Request body
{
  "url": "https://pos.cafearoma.mx/webhooks/pokit",
  "description": "Punto de venta de Sucursal Centro",
  "events": [
    "balance.earned",
    "balance.redeemed",
    "card.created"
  ]
}
Respuesta 201 · URL creada, con su `secret`.
{
  "id": "cmwhk2b7c0001pokitwhk01",
  "url": "https://pos.cafearoma.mx/webhooks/pokit",
  "description": "Punto de venta de Sucursal Centro",
  "events": [
    "balance.earned",
    "balance.redeemed",
    "card.created"
  ],
  "enabled": true,
  "createdAt": "2026-10-15T16:20:00.000Z",
  "updatedAt": "2026-10-15T16:20:00.000Z",
  "secret": "whsec_2f8a6c1e9b0d4a7f3c5e8b1d6a9f0c2e4b7d1a3c5e8f0b2d"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 409 Ya tienes el máximo de 10 URLs.
  • 422 Body inválido, evento desconocido o URL no permitida (no es https o apunta a una red interna).
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /webhooks/{id}

Obtener URL de webhook

La URL con su `secret` vigente, para configurar la verificación de la firma.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
Ejemplo · curl
curl "https://pokit.mx/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · La URL con su `secret`.
{
  "id": "cmwhk2b7c0001pokitwhk01",
  "url": "https://pos.cafearoma.mx/webhooks/pokit",
  "description": "Punto de venta de Sucursal Centro",
  "events": [
    "balance.earned",
    "balance.redeemed",
    "card.created"
  ],
  "enabled": true,
  "createdAt": "2026-10-15T16:20:00.000Z",
  "updatedAt": "2026-10-15T16:20:00.000Z",
  "secret": "whsec_2f8a6c1e9b0d4a7f3c5e8b1d6a9f0c2e4b7d1a3c5e8f0b2d"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
PATCH /webhooks/{id}

Editar URL de webhook

Cambia sólo los campos enviados; el resultado se valida completo. Con `enabled: false` deja de recibir eventos nuevos (los reintentos pendientes se marcan `failed`).

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
Ejemplo · curl
curl -X PATCH "https://pokit.mx/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "events": [
    "balance.earned",
    "balance.redeemed",
    "coupon.redeemed"
  ],
  "enabled": true
}'
Request body
{
  "events": [
    "balance.earned",
    "balance.redeemed",
    "coupon.redeemed"
  ],
  "enabled": true
}
Respuesta 200 · URL actualizada.
{
  "id": "cmwhk2b7c0001pokitwhk01",
  "url": "https://pos.cafearoma.mx/webhooks/pokit",
  "description": "Punto de venta de Sucursal Centro",
  "events": [
    "balance.earned",
    "balance.redeemed",
    "coupon.redeemed"
  ],
  "enabled": true,
  "createdAt": "2026-10-15T16:20:00.000Z",
  "updatedAt": "2026-10-15T16:20:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
DELETE /webhooks/{id}

Eliminar URL de webhook

Deja de recibir eventos y se borra su bitácora de entregas.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
Ejemplo · curl
curl -X DELETE "https://pokit.mx/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /webhooks/{id}/test

Enviar evento de prueba

Envía un evento `webhook.test` firmado a la URL (aunque esté en pausa) y responde con el resultado de ese intento. La prueba no se reintenta. Sin cuerpo.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/webhooks/{id}/test" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Resultado de la prueba: `delivered` si respondió 2xx; si no, `failed` con el error.
{
  "id": "cmdlv3n8q0001pokitdlvr1",
  "endpointId": "cmwhk2b7c0001pokitwhk01",
  "eventId": "evt_5f2c9a1e7b3d4c6f8a0b1c2d",
  "type": "webhook.test",
  "status": "delivered",
  "attempts": 1,
  "lastStatus": 200,
  "lastError": null,
  "nextAttemptAt": null,
  "deliveredAt": "2026-10-15T18:42:07.480Z",
  "createdAt": "2026-10-15T18:42:07.120Z",
  "payload": {
    "id": "evt_9a0b1c2d3e4f5a6b7c8d9e0f",
    "type": "webhook.test",
    "createdAt": "2026-10-15T18:42:07.120Z",
    "businessId": "cmbiz7k2p0001pokitbizn1",
    "data": {
      "message": "Prueba de Pokit: si ves esto, tu URL recibe y verifica eventos.",
      "endpointId": "cmwhk2b7c0001pokitwhk01"
    }
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /webhooks/{id}/rotate-secret

Rotar el secret

Genera un `secret` nuevo. El anterior deja de valer en ese momento: todo lo que salga desde ahora, incluidos los reintentos pendientes, va firmado con el nuevo. Sin cuerpo.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/webhooks/{id}/rotate-secret" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · El `secret` nuevo.
{
  "id": "cmwhk2b7c0001pokitwhk01",
  "secret": "whsec_2f8a6c1e9b0d4a7f3c5e8b1d6a9f0c2e4b7d1a3c5e8f0b2d"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /webhooks/{id}/deliveries

Listar entregas

La bitácora de entregas de la URL, de la más reciente a la más antigua: una por evento, con su estado (`pending` mientras reintenta, `delivered`, `failed`), intentos, último código HTTP y error. Se guardan 30 días.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
statusquerystringFiltra por estado.
limitqueryintegerCuántas devolver (1 a 200, por defecto 50).
Ejemplo · curl
curl "https://pokit.mx/api/v1/webhooks/{id}/deliveries" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Entregas de la URL.
[
  {
    "id": "cmdlv3n8q0001pokitdlvr1",
    "endpointId": "cmwhk2b7c0001pokitwhk01",
    "eventId": "evt_5f2c9a1e7b3d4c6f8a0b1c2d",
    "type": "balance.earned",
    "status": "pending",
    "attempts": 2,
    "lastStatus": 503,
    "lastError": "HTTP 503: Service Unavailable",
    "nextAttemptAt": "2026-10-15T18:52:07.000Z",
    "deliveredAt": null,
    "createdAt": "2026-10-15T18:42:07.120Z",
    "payload": {
      "id": "evt_5f2c9a1e7b3d4c6f8a0b1c2d",
      "type": "balance.earned",
      "createdAt": "2026-10-15T18:42:07.120Z",
      "businessId": "cmbiz7k2p0001pokitbizn1",
      "data": {
        "card": {
          "id": "cmcrd8f2k0001pokitcard1"
        },
        "field": "points",
        "delta": 10,
        "balance": 130
      }
    }
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /webhooks/{id}/deliveries/{deliveryId}/retry

Reintentar una entrega

Intenta la entrega ahora (también una ya entregada, para reenviarla) y responde con el resultado. Si falla, sigue el calendario de reintentos donde iba; si ya lo había agotado, vuelve a quedar `failed`. Sin cuerpo.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la URL de webhook.
deliveryId*pathstringID de la entrega.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/webhooks/{id}/deliveries/{deliveryId}/retry" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · La entrega tras el intento.
{
  "id": "cmdlv3n8q0001pokitdlvr1",
  "endpointId": "cmwhk2b7c0001pokitwhk01",
  "eventId": "evt_5f2c9a1e7b3d4c6f8a0b1c2d",
  "type": "balance.earned",
  "status": "delivered",
  "attempts": 3,
  "lastStatus": 200,
  "lastError": null,
  "nextAttemptAt": null,
  "deliveredAt": "2026-10-15T19:01:12.000Z",
  "createdAt": "2026-10-15T18:42:07.120Z",
  "payload": {
    "id": "evt_5f2c9a1e7b3d4c6f8a0b1c2d",
    "type": "balance.earned",
    "createdAt": "2026-10-15T18:42:07.120Z",
    "businessId": "cmbiz7k2p0001pokitbizn1",
    "data": {
      "card": {
        "id": "cmcrd8f2k0001pokitcard1"
      },
      "field": "points",
      "delta": 10,
      "balance": 130
    }
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 La entrega no existe, no es de esa URL o ya se borró (se guardan 30 días).
  • 429 Límite de 120 solicitudes por minuto excedido.

Sucursales

GET /branches

Listar sucursales

Las sucursales de tu negocio, activas o no, en el orden en que se dieron de alta. Cada plantilla vale en las sucursales que elijas en el panel (o en todas) y lleva hasta 10 a su pase de Wallet: el pase aparece en la pantalla de bloqueo del cliente cuando está cerca de una de ellas.

Ejemplo · curl
curl "https://pokit.mx/api/v1/branches" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Lista de sucursales.
[
  {
    "id": "cmbrc4k9p0007pokitbrc01",
    "name": "Okuma Polanco",
    "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
    "latitude": 19.4326,
    "longitude": -99.1937,
    "relevantText": "¡Estás cerca de Okuma Polanco! Muestra tu tarjeta.",
    "active": true,
    "createdAt": "2026-09-02T16:20:00.000Z"
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /branches

Crear sucursal

Da de alta una sucursal: un punto en el mapa con el mensaje que verá el cliente en su pantalla de bloqueo al acercarse. Las plantillas que valen en todas las sucursales la incluyen en sus pases de inmediato; a las demás se agrega desde el panel.

Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/branches" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Okuma Polanco",
  "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
  "latitude": 19.4326,
  "longitude": -99.1937,
  "relevantText": "¡Estás cerca de Okuma Polanco! Muestra tu tarjeta."
}'
Request body
{
  "name": "Okuma Polanco",
  "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
  "latitude": 19.4326,
  "longitude": -99.1937,
  "relevantText": "¡Estás cerca de Okuma Polanco! Muestra tu tarjeta."
}
Respuesta 201 · Sucursal creada.
{
  "id": "cmbrc4k9p0007pokitbrc01",
  "name": "Okuma Polanco",
  "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
  "latitude": 19.4326,
  "longitude": -99.1937,
  "relevantText": "¡Estás cerca de Okuma Polanco! Muestra tu tarjeta.",
  "active": true,
  "createdAt": "2026-09-02T16:20:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 422 Body inválido: falta el nombre o las coordenadas están fuera de rango.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /branches/{id}

Obtener sucursal

Parámetros

NombreEnTipoDescripción
id*pathstringID de la sucursal.
Ejemplo · curl
curl "https://pokit.mx/api/v1/branches/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · La sucursal.
{
  "id": "cmbrc4k9p0007pokitbrc01",
  "name": "Okuma Polanco",
  "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
  "latitude": 19.4326,
  "longitude": -99.1937,
  "relevantText": "¡Estás cerca de Okuma Polanco! Muestra tu tarjeta.",
  "active": true,
  "createdAt": "2026-09-02T16:20:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
PATCH /branches/{id}

Editar sucursal

Cambia sólo los campos enviados. Con `active: false` la sucursal deja de aparecer en los pases y en la Caja, pero conserva su historial y sus estadísticas: es lo recomendable para una sucursal que cerró. Los pases ya instalados se actualizan solos.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la sucursal.
Ejemplo · curl
curl -X PATCH "https://pokit.mx/api/v1/branches/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "relevantText": "Nuevo horario: abrimos a las 7 am",
  "active": true
}'
Request body
{
  "relevantText": "Nuevo horario: abrimos a las 7 am",
  "active": true
}
Respuesta 200 · Sucursal actualizada.
{
  "id": "cmbrc4k9p0007pokitbrc01",
  "name": "Okuma Polanco",
  "address": "Av. Presidente Masaryk 120, Polanco, CDMX",
  "latitude": 19.4326,
  "longitude": -99.1937,
  "relevantText": "Nuevo horario: abrimos a las 7 am",
  "active": true,
  "createdAt": "2026-09-02T16:20:00.000Z"
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 422 Body vacío o con valores inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
DELETE /branches/{id}

Borrar sucursal

Borra la sucursal para siempre. Sus movimientos se conservan, pero sin sucursal: si quieres seguir viéndola en las estadísticas, mejor desactívala con `PATCH` y `active: false`.

Parámetros

NombreEnTipoDescripción
id*pathstringID de la sucursal.
Ejemplo · curl
curl -X DELETE "https://pokit.mx/api/v1/branches/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.

Clientes

GET /customers

Listar clientes

Lista paginada de los perfiles de cliente de tu negocio. Un perfil une todas las tarjetas de una persona (de distintas plantillas): las tarjetas nuevas con el mismo teléfono se ligan solas, y desde el panel o con `/merge` y `/split` se unen o separan a mano. Los más recientes (por última visita) van primero. Cada fila trae cuántas tarjetas tiene, sus visitas (movimientos `earn`) y su última visita.

Parámetros

NombreEnTipoDescripción
qquerystringBusca por nombre, correo, teléfono (basta con los últimos dígitos), número de socio (8 dígitos) o serial de cualquiera de sus tarjetas.
pagequeryintegerPágina (desde 1).
limitqueryintegerResultados por página (máx. 100).
Ejemplo · curl
curl "https://pokit.mx/api/v1/customers" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Página de clientes.
{
  "data": [
    {
      "id": "cmcus3k8p0005pokitcust1",
      "name": "María González",
      "email": "maria@ejemplo.com",
      "phone": "5512345678",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-07-18T09:12:00.000Z",
      "cards": 2,
      "visits": 14,
      "lastVisit": "2026-10-12T19:04:00.000Z"
    }
  ],
  "page": 1,
  "limit": 20,
  "total": 87
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
GET /customers/{id}

Obtener cliente

El perfil con todas sus tarjetas y sus métricas: visitas, última visita, visitas al mes (últimos 90 días), sucursal favorita, cupones canjeados y ticket promedio. `favoriteBranch` es `null` si sus movimientos no traen sucursal; `averageTicket` es `null` si tu caja no manda `metadata.total` numérico al sumar.

Parámetros

NombreEnTipoDescripción
id*pathstringID del perfil del cliente (el `customerId` de sus tarjetas).
Ejemplo · curl
curl "https://pokit.mx/api/v1/customers/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · El perfil.
{
  "id": "cmcus3k8p0005pokitcust1",
  "name": "María González",
  "email": "maria@ejemplo.com",
  "phone": "5512345678",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z",
  "cards": [
    {
      "id": "cmcrd8f2k0001pokitcard1",
      "serial": "cmsrl4x9m0002pokitserl1",
      "memberNumber": "48213907",
      "templateId": "cmtpl1a2b0003pokittmpl1",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 120,
      "stamps": 0,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Café Club"
    },
    {
      "id": "cmcrd9a1b0007pokitcard2",
      "serial": "cmsrl5y0n0008pokitserl2",
      "memberNumber": "71592036",
      "templateId": "cmtpl2c3d0009pokittmpl2",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 0,
      "stamps": 6,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Sellos de pan"
    }
  ],
  "metrics": {
    "visits": 14,
    "lastVisit": "2026-10-12T19:04:00.000Z",
    "visitsPerMonth": 3.3,
    "favoriteBranch": {
      "id": "cmbrn2h6t0006pokitbrnc1",
      "name": "Sucursal Centro",
      "visits": 11
    },
    "couponsRedeemed": 2,
    "averageTicket": 186.5
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El perfil no existe o no pertenece a tu negocio.
  • 429 Límite de 120 solicitudes por minuto excedido.
PATCH /customers/{id}

Editar cliente

Cambia los datos de contacto del perfil. Sólo cambian los campos enviados; `null` o una cadena vacía borran el correo o el teléfono. El nombre y el correo de cada tarjeta (lo que muestra el pase) no cambian. El correo se guarda en minúsculas y el teléfono sólo con dígitos.

Parámetros

NombreEnTipoDescripción
id*pathstringID del perfil del cliente.
Ejemplo · curl
curl -X PATCH "https://pokit.mx/api/v1/customers/{id}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "María González Ruiz",
  "phone": "+52 55 1234 5678"
}'
Request body
{
  "name": "María González Ruiz",
  "phone": "+52 55 1234 5678"
}
Respuesta 200 · Perfil actualizado, con sus tarjetas y métricas.
{
  "id": "cmcus3k8p0005pokitcust1",
  "name": "María González Ruiz",
  "email": "maria@ejemplo.com",
  "phone": "+525512345678",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z",
  "cards": [
    {
      "id": "cmcrd8f2k0001pokitcard1",
      "serial": "cmsrl4x9m0002pokitserl1",
      "memberNumber": "48213907",
      "templateId": "cmtpl1a2b0003pokittmpl1",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 120,
      "stamps": 0,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Café Club"
    },
    {
      "id": "cmcrd9a1b0007pokitcard2",
      "serial": "cmsrl5y0n0008pokitserl2",
      "memberNumber": "71592036",
      "templateId": "cmtpl2c3d0009pokittmpl2",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 0,
      "stamps": 6,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Sellos de pan"
    }
  ],
  "metrics": {
    "visits": 14,
    "lastVisit": "2026-10-12T19:04:00.000Z",
    "visitsPerMonth": 3.3,
    "favoriteBranch": {
      "id": "cmbrn2h6t0006pokitbrnc1",
      "name": "Sucursal Centro",
      "visits": 11
    },
    "couponsRedeemed": 2,
    "averageTicket": 186.5
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El perfil no existe o no pertenece a tu negocio.
  • 422 Body inválido o con campos desconocidos.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /customers/{id}/merge

Unir clientes

Funde el perfil `customerId` en éste (`{id}`): sus tarjetas pasan a este perfil, los datos vacíos de éste se completan con los del otro y el otro perfil se borra. No se puede deshacer de golpe: para revertirlo, separa las tarjetas con `/split`. Ambos perfiles deben ser de tu negocio.

Parámetros

NombreEnTipoDescripción
id*pathstringID del perfil que se queda.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/customers/{id}/merge" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "cmcus7z2q0010pokitcust2"
}'
Request body
{
  "customerId": "cmcus7z2q0010pokitcust2"
}
Respuesta 200 · Perfil resultante, con todas las tarjetas.
{
  "id": "cmcus3k8p0005pokitcust1",
  "name": "María González",
  "email": "maria@ejemplo.com",
  "phone": "5512345678",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z",
  "cards": [
    {
      "id": "cmcrd8f2k0001pokitcard1",
      "serial": "cmsrl4x9m0002pokitserl1",
      "memberNumber": "48213907",
      "templateId": "cmtpl1a2b0003pokittmpl1",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 120,
      "stamps": 0,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Café Club"
    },
    {
      "id": "cmcrd9a1b0007pokitcard2",
      "serial": "cmsrl5y0n0008pokitserl2",
      "memberNumber": "71592036",
      "templateId": "cmtpl2c3d0009pokittmpl2",
      "customerId": "cmcus3k8p0005pokitcust1",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 0,
      "stamps": 6,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Sellos de pan"
    }
  ],
  "metrics": {
    "visits": 14,
    "lastVisit": "2026-10-12T19:04:00.000Z",
    "visitsPerMonth": 3.3,
    "favoriteBranch": {
      "id": "cmbrn2h6t0006pokitbrnc1",
      "name": "Sucursal Centro",
      "visits": 11
    },
    "couponsRedeemed": 2,
    "averageTicket": 186.5
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 Alguno de los dos perfiles no existe o no pertenece a tu negocio.
  • 422 Falta `customerId` o es el mismo perfil.
  • 429 Límite de 120 solicitudes por minuto excedido.
POST /customers/{id}/split

Separar tarjeta

Saca la tarjeta `cardId` de este perfil a un perfil nuevo, con el nombre, correo y teléfono de su alta. Úsalo cuando se unieron dos personas distintas. La tarjeta debe ser de este perfil y el perfil debe tener al menos dos tarjetas. Responde con el perfil nuevo.

Parámetros

NombreEnTipoDescripción
id*pathstringID del perfil del que sale la tarjeta.
Ejemplo · curl
curl -X POST "https://pokit.mx/api/v1/customers/{id}/split" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "cardId": "cmcrd9a1b0007pokitcard2"
}'
Request body
{
  "cardId": "cmcrd9a1b0007pokitcard2"
}
Respuesta 201 · Perfil nuevo con la tarjeta separada.
{
  "id": "cmcus8w4r0011pokitcust3",
  "name": "María González",
  "email": "maria@ejemplo.com",
  "phone": "5512345678",
  "createdAt": "2026-07-01T15:30:00.000Z",
  "updatedAt": "2026-07-18T09:12:00.000Z",
  "cards": [
    {
      "id": "cmcrd9a1b0007pokitcard2",
      "serial": "cmsrl5y0n0008pokitserl2",
      "memberNumber": "71592036",
      "templateId": "cmtpl2c3d0009pokittmpl2",
      "customerId": "cmcus8w4r0011pokitcust3",
      "homeBranchId": "cmbrn2h6t0006pokitbrnc1",
      "lastBranchId": "cmbrn2h6t0006pokitbrnc1",
      "customerName": "María González",
      "customerEmail": "maria@ejemplo.com",
      "customerPhone": "5512345678",
      "data": {},
      "points": 0,
      "stamps": 6,
      "status": "ACTIVE",
      "lastActivityAt": "2026-10-12T19:04:00.000Z",
      "createdAt": "2026-07-01T15:30:00.000Z",
      "updatedAt": "2026-10-12T19:04:00.000Z",
      "templateName": "Sellos de pan"
    }
  ],
  "metrics": {
    "visits": 6,
    "lastVisit": "2026-10-03T13:20:00.000Z",
    "visitsPerMonth": 1.3,
    "favoriteBranch": null,
    "couponsRedeemed": 0,
    "averageTicket": null
  }
}

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El perfil o la tarjeta no existen, o la tarjeta no es de este perfil.
  • 409 Es la única tarjeta del perfil: no hay nada que separar.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.

Ubicaciones

GET /locations

Listar ubicaciones

Obsoleto: usa `GET /branches` y el campo `branches` de `GET /templates/{id}`. Devuelve las sucursales activas donde vale la plantilla con la forma de antes (`templateId` es el de la plantilla consultada); se mantiene para no romper integraciones.

Parámetros

NombreEnTipoDescripción
templateId*querystringID de la plantilla.
Ejemplo · curl
curl "https://pokit.mx/api/v1/locations?templateId={templateId}" \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx"
Respuesta 200 · Sucursales de la plantilla, con la forma de las antiguas ubicaciones.
[
  {
    "id": "cmloc7q1w0004pokitloc01",
    "templateId": "cmtpl1a2b0003pokittmpl1",
    "name": "Sucursal Centro",
    "latitude": 19.4326,
    "longitude": -99.1332,
    "relevantText": "¡Estás cerca de Café Aroma! Muestra tu tarjeta."
  }
]

Otros códigos

  • 401 API key faltante, malformada o revocada.
  • 404 El recurso no existe o no pertenece a tu negocio.
  • 422 Parámetros o body inválidos.
  • 429 Límite de 120 solicitudes por minuto excedido.

Spec completa disponible en /api/openapi.json (OpenAPI 3.1). ¿Dudas? Escríbenos desde el panel.

GET https://pokit.mx/api/v1