Saltar al contenido

Desarrolladores

La API de Kambak

Sumá sellos desde tu caja, creá clientes desde tu tienda y recibí webhooks. REST, JSON y OpenAPI 3.1.

Desde el plan Inicial (API para tu caja). Completa y con webhooks desde Pro.

Guía rápida

  1. Creá una clave en Panel › Integraciones. Arrancá con una de prueba (kbk_test_…).
  2. Probala con GET /me:

    curl https://api.kambak.app/api/v1/me \
      -H "Authorization: Bearer $KAMBAK_API_KEY"
  3. Sumá un sello. Toda escritura lleva una Idempotency-Key:

    curl -X POST https://api.kambak.app/api/v1/cards/CARD_ID/actions \
      -H "Authorization: Bearer $KAMBAK_API_KEY" \
      -H "Idempotency-Key: venta-1042" \
      -H "Content-Type: application/json" \
      -d '{"action": "stamp", "count": 1}'

Base: https://api.kambak.app/api/v1

Qué incluye cada plan

PlanAPIPedidos/min
GratisSin API—
InicialAPI para tu caja: clientes, tarjetas, emitir y acciones60
ProAPI completa: también campañas, estadísticas y webhooks120
MultisedeTodo, claves por sucursal y servidor MCP600

Si bajás de plan, lo que ya no incluye responde 403 plan_upgrade_required. La operación dice su plan mínimo en x-kambak-plan.

Autenticación

Mandá la clave en el header Authorization: Bearer kbk_live_….

La clave se muestra una sola vez. Guardala en tu servidor, nunca en el navegador ni en una app.

Actúa con los permisos del dueño que la creó. Si deja de ser dueño, deja de andar.

Revocarla la corta al instante.

Permisos (scopes)

customers:read
Ver clientes
customers:write
Crear y editar clientes
cards:read
Ver tarjetas e historial
cards:write
Sumar, restar y canjear; emitir tarjetas
programs:read
Ver tus programas
campaigns:read
Ver campañas y cupo
campaigns:write
Crear y mandar avisos (con el cupo del plan)
stats:read
Ver estadísticas
webhooks:read
Ver webhooks y entregas
webhooks:write
Crear y borrar webhooks

Modo test

Las claves kbk_test_… leen los datos reales de tu comercio.

Las escrituras se validan y simulan: te devuelven lo que pasaría, pero no se guarda nada.

No se actualiza Wallet, no sale ningún aviso y no se disparan webhooks.

Cada respuesta trae Kambak-Mode: test; /me devuelve livemode: false.

Idempotencia

Toda escritura (POST, PATCH, DELETE) exige Idempotency-Key: un valor único por operación.

Si tu caja reintenta con la misma key, recibe la misma respuesta y no se suma dos veces (Idempotent-Replayed: true).

La misma key con otro cuerpo devuelve 422 idempotency_key_reused.

Se recuerda 24 h. Si la operación falló, podés reintentar con la misma key.

Errores

Siempre el mismo formato. Usá code en tu código; message está en español.

{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta clave no tiene el permiso cards:write",
    "details": { "required": "cards:write" }
  }
}
validation_error
400 · datos inválidos (en details, campo por campo)
idempotency_key_required
400 · falta la Idempotency-Key
invalid_api_key
401 · clave inválida, revocada o inactiva
insufficient_scope
403 · la clave no tiene ese permiso
plan_upgrade_required
403 · tu plan no incluye esa operación (details.requiredPlan)
merchant_inactive
403 · el comercio está suspendido o cerrado
not_found
404 · no existe en tu comercio
recent_action
409 · la misma acción hace menos de 2 min: confirmá con confirmRepeat
rate_limited
429 · pasaste el límite por minuto

Paginación

Las listas devuelven data y nextCursor. Pasalo como ?cursor= hasta que venga null.

limit va de 1 a 100 (default 20).

Límites

Por clave: 60 pedidos por minuto en Inicial, 120 en Pro y 600 en Multisede. También hay un tope por comercio.

Cada respuesta trae RateLimit-Limit, RateLimit-Remaining y RateLimit-Reset.

Con 429, esperá lo que dice Retry-After.

Los avisos respetan el cupo de campañas del plan y el tope de 3 por pase cada 24 h de Google.

Webhooks

Registrá una URL y elegí eventos. Te mandamos un POST con JSON firmado.

Creá webhooks en Integraciones o con POST /webhook-endpoints (ideal para Zapier).

Respondé 2xx en menos de 5 s. Si no, reintentamos 8 veces con esperas crecientes (~4 h).

Tras 10 entregas fallidas seguidas, o muchos timeouts seguidos, pausamos el webhook y te avisamos por mail.

Por API, cada evento pide su permiso de lectura: customer.* → customers:read; el resto → cards:read.

Solo URLs https de servidores públicos.

Llegan en segundos; algunos (como Wallet) hasta 1 minuto después.

Eventos

customer.created
Cliente nuevo
card.created
Tarjeta nueva
card.stamped
Sumó sellos
card.points_changed
Sumó puntos
card.balance_changed
Usó saldo de gift card
card.adjusted
Ajuste manual
card.action_undone
Acción deshecha
reward.redeemed
Canjeó un premio o cupón
membership.checked
Validó la membresía
membership.payment_received
Pagó la membresía
membership.payment_reverted
Pago de membresía revertido
membership.cancelled
Canceló el débito
pass.saved
Guardó el pase en Wallet
pass.removed
Eliminó el pase de Wallet

Así llega cada evento:

{
  "id": "evt_3f9c1b2a7d4e5f60a1b2c3d4",
  "type": "card.stamped",
  "createdAt": "2026-10-13T15:04:05.000Z",
  "livemode": true,
  "merchantId": "6c0f…",
  "data": {
    "card": { "id": "…", "programId": "…", "programType": "stamps", "customerId": "…", "memberNumber": "3F2A91BC" },
    "event": { "id": "…", "kind": "stamp", "delta": "1", "before": 6, "after": 7, "origin": "api" }
  }
}

Verificar la firma

El header Kambak-Signature trae t=…,v1=….

  1. Calculá HMAC-SHA256 de t + "." + cuerpo crudo con tu secreto whsec_….
  2. Compará con v1 en tiempo constante.
  3. Rechazá si t tiene más de 5 minutos (anti-replay).

Usá id del evento para ignorar duplicados.

import crypto from 'node:crypto';
import express from 'express';

const app = express();
const SECRET = process.env.KAMBAK_WEBHOOK_SECRET; // whsec_…

// El cuerpo CRUDO: la firma es sobre los bytes tal cual llegaron
app.post('/webhooks/kambak', express.raw({ type: 'application/json' }), (req, res) => {
  const parts = Object.fromEntries(
    (req.get('Kambak-Signature') ?? '').split(',').map((p) => p.split('=')),
  );
  const expected = crypto
    .createHmac('sha256', SECRET)
    .update(`${parts.t}.${req.body}`)
    .digest('hex');
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  const valid =
    fresh &&
    typeof parts.v1 === 'string' &&
    parts.v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
  if (!valid) return res.status(400).send('invalid signature');

  const event = JSON.parse(req.body);
  // Guardá event.id para ignorar duplicados
  if (event.type === 'reward.redeemed') {
    // …
  }
  res.sendStatus(200);
});

Referencia

Generada del mismo OpenAPI que valida la API.

openapi.json

Cuenta

get/meComercio y clave actuales

Ideal para la primera llamada: confirma que la clave anda.

Plan mínimo: Inicial

Respuesta 200 · Me

merchantobjectobligatorio
apiKeyobjectobligatorio
accessobjectobligatorio
Qué incluye el plan: pos (Inicial: lo de la caja) o full (Pro y Multisede).
livemodebooleanobligatorio

Clientes

get/customersListar o buscar clientes
Plan mínimo: InicialPermiso: customers:read

Parámetros

limit (query)integer
Tamaño de página (1–100).
cursor (query)string
El nextCursor de la página anterior.
q (query)string
Buscar por nombre, email o teléfono.
email (query)string (email)
Email exacto (sin distinguir mayúsculas).

Respuesta 200 · CustomerList

dataCustomer[]obligatorio
nextCursorstring | nullobligatorio
Pasalo como cursor para seguir.
post/customersCrear un cliente

Promociones solo con consentimiento real: mandá consentSource. Email repetido → 409 customer_exists.

Errores: customer_exists.

Plan mínimo: InicialPermiso: customers:writeIdempotency-Key

Cuerpo CreateCustomerInput

namestring
emailstring (email)
phonestring
Teléfono (WhatsApp), con código de país.
birthDatestring (date)
AAAA-MM-DD.
consentMarketingboolean
Solo true si el cliente aceptó recibir promociones.
consentSourcestring
Cómo aceptó el cliente (p. ej. "Casilla en el checkout web"). Obligatorio para dar el consentimiento.

Respuesta 201 · Customer

idstring (uuid)obligatorio
namestring | nullobligatorio
emailstring | nullobligatorio
phonestring | nullobligatorio
birthDatestring (date) | nullobligatorio
AAAA-MM-DD.
consentMarketingbooleanobligatorio
Aceptó recibir promociones.
consentMarketingAtstring (date-time) | nullobligatorio
Cuándo aceptó.
createdVia"qr" | "nfc" | "link" | "panel" | "import" | "api" | …obligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
get/customers/{id}Obtener un cliente
Plan mínimo: InicialPermiso: customers:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · Customer

idstring (uuid)obligatorio
namestring | nullobligatorio
emailstring | nullobligatorio
phonestring | nullobligatorio
birthDatestring (date) | nullobligatorio
AAAA-MM-DD.
consentMarketingbooleanobligatorio
Aceptó recibir promociones.
consentMarketingAtstring (date-time) | nullobligatorio
Cuándo aceptó.
createdVia"qr" | "nfc" | "link" | "panel" | "import" | "api" | …obligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
patch/customers/{id}Actualizar un cliente

null borra un dato. Dar el consentimiento exige consentSource; retirarlo, no.

Errores: email_taken.

Plan mínimo: ProPermiso: customers:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Cuerpo UpdateCustomerInput

namestring | null
emailstring (email) | null
phonestring | null
birthDatestring (date) | null
consentMarketingboolean
false retira el consentimiento.
consentSourcestring
Cómo aceptó el cliente (p. ej. "Casilla en el checkout web"). Obligatorio para dar el consentimiento.

Respuesta 200 · Customer

idstring (uuid)obligatorio
namestring | nullobligatorio
emailstring | nullobligatorio
phonestring | nullobligatorio
birthDatestring (date) | nullobligatorio
AAAA-MM-DD.
consentMarketingbooleanobligatorio
Aceptó recibir promociones.
consentMarketingAtstring (date-time) | nullobligatorio
Cuándo aceptó.
createdVia"qr" | "nfc" | "link" | "panel" | "import" | "api" | …obligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
get/customers/{id}/cardsTarjetas de un cliente
Plan mínimo: InicialPermiso: cards:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · CardList

dataCard[]obligatorio
nextCursorstring | nullobligatorio
Pasalo como cursor para seguir.

Tarjetas

get/cardsListar tarjetas
Plan mínimo: ProPermiso: cards:read

Parámetros

limit (query)integer
Tamaño de página (1–100).
cursor (query)string
El nextCursor de la página anterior.
customerId (query)string (uuid)
programId (query)string (uuid)

Respuesta 200 · CardList

dataCard[]obligatorio
nextCursorstring | nullobligatorio
Pasalo como cursor para seguir.
post/cardsEmitir una tarjeta

Crea la tarjeta del cliente en un programa activo y devuelve los links de Wallet. Si ya existía, la devuelve (200).

Errores: program_not_active, customer_not_found.

Plan mínimo: InicialPermiso: cards:writeIdempotency-Key

Cuerpo IssueCardInput

customerIdstring (uuid)obligatorio
programIdstring (uuid)obligatorio
Un programa activo.

Respuesta 201 · IssueCardResult

cardCardobligatorio
createdbooleanobligatorio
false si ya existía.
walletWalletLinksobligatorio
get/cards/{id}Obtener una tarjeta

Errores: card_not_found.

Plan mínimo: InicialPermiso: cards:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · Card

idstring (uuid)obligatorio
programIdstring (uuid)obligatorio
customerIdstring (uuid)obligatorio
programType"stamps" | "points" | "membership" | "coupon" | "giftcard"obligatorio
programNamestringobligatorio
status"active" | "suspended" | "expired" | "revoked"obligatorio
memberNumberstringobligatorio
N° de socio del pase.
summarystringobligatorio
Lo que muestra el pase ("7 de 10").
stateCardStateobligatorio
walletobjectobligatorio
canEarnbooleanobligatorio
blockedReasonstring | nullobligatorio
createdAtstring (date-time)obligatorio
lastUsedAtstring (date-time) | nullobligatorio
get/cards/by-code/{code}Buscar por el QR del pase

Pasá lo que leyó el lector (URL-encoded).

Errores: card_not_found.

Plan mínimo: InicialPermiso: cards:read

Parámetros

code (path)stringobligatorio
Lo que lee el QR del pase.

Respuesta 200 · Card

idstring (uuid)obligatorio
programIdstring (uuid)obligatorio
customerIdstring (uuid)obligatorio
programType"stamps" | "points" | "membership" | "coupon" | "giftcard"obligatorio
programNamestringobligatorio
status"active" | "suspended" | "expired" | "revoked"obligatorio
memberNumberstringobligatorio
N° de socio del pase.
summarystringobligatorio
Lo que muestra el pase ("7 de 10").
stateCardStateobligatorio
walletobjectobligatorio
canEarnbooleanobligatorio
blockedReasonstring | nullobligatorio
createdAtstring (date-time)obligatorio
lastUsedAtstring (date-time) | nullobligatorio
get/cards/{id}/eventsHistorial de la tarjeta
Plan mínimo: InicialPermiso: cards:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.
limit (query)integer

Respuesta 200 · CardEventList

dataCardEvent[]obligatorio
post/cards/{id}/actionsSumar, restar o canjear

Mismas reglas que el escáner: historial, Wallet y deshacer. Restar = adjust con delta negativo.

Errores: recent_action, card_inactive, reward_pending, reward_not_available, not_enough_points, insufficient_balance, coupon_used, max_stamps_per_visit.

Plan mínimo: InicialPermiso: cards:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Cuerpo CardActionInput

Una de estas formas:

action: "stamp"

countinteger
confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "redeem_stamps"

confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "add_points"

amountnumberobligatorio
Importe de la compra.
confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "redeem_points"

rewardPointsintegerobligatorio
Costo del premio.
confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "giftcard_debit"

amountnumberobligatorio
Monto en unidades, hasta 2 decimales.
confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "membership_check"

confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "coupon_use"

purchaseAmountnumber
Monto en unidades, hasta 2 decimales.
confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

action: "adjust"

field"stamps" | "points" | "balance" | "uses"obligatorio
deltanumberobligatorio
Con signo: negativo resta.
reasonstringobligatorio
confirmRepeatboolean
Confirma que no es un doble escaneo (409 recent_action).
locationIdstring (uuid) | null

Respuesta 200 · CardActionResult

cardCardobligatorio
eventCardEventobligatorio
messagestringobligatorio
rewardAvailablebooleanobligatorio
replayedbooleanobligatorio
post/cards/{id}/events/{eventId}/undoDeshacer la última acción

Dentro de los 5 minutos.

Errores: undo_expired, not_last_action, already_undone.

Plan mínimo: InicialPermiso: cards:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
eventId (path)string (uuid)obligatorio

Respuesta 200 · CardActionResult

cardCardobligatorio
eventCardEventobligatorio
messagestringobligatorio
rewardAvailablebooleanobligatorio
replayedbooleanobligatorio

Programas

get/programsListar programas
Plan mínimo: InicialPermiso: programs:read

Respuesta 200 · ProgramList

dataProgram[]obligatorio
get/programs/{id}Obtener un programa
Plan mínimo: InicialPermiso: programs:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · Program

idstring (uuid)obligatorio
type"stamps" | "points" | "membership" | "coupon" | "giftcard"obligatorio
namestringobligatorio
descriptionstring | nullobligatorio
termsstring | nullobligatorio
status"draft" | "active" | "paused" | "archived"obligatorio
benefitstringobligatorio
Frase corta del beneficio.
rulesobjectobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio

Campañas y avisos

get/campaignsListar campañas
Plan mínimo: ProPermiso: campaigns:read

Parámetros

limit (query)integer
Tamaño de página (1–100).
cursor (query)string
El nextCursor de la página anterior.

Respuesta 200 · CampaignList

dataCampaign[]obligatorio
nextCursorstring | nullobligatorio
Pasalo como cursor para seguir.
post/campaignsCrear un aviso (borrador)
Plan mínimo: ProPermiso: campaigns:writeIdempotency-Key

Cuerpo CreateCampaignInput

titlestringobligatorio
Hasta 40 caracteres.
textstringobligatorio
Hasta 300 caracteres.
programIdstring (uuid)obligatorio
segmentIdstring (uuid)
Un segmento guardado.
segmentPreset"inactive_30" | "one_stamp_left" | "birthday_month" | "new_this_week" | "vip_10" | "wallet_removed_30"
customerIdsstring (uuid)[]
Aviso directo a estos clientes (1–500). Cuenta como una campaña.

Respuesta 201 · Campaign

idstring (uuid)obligatorio
programIdstring (uuid) | nullobligatorio
segmentIdstring (uuid) | nullobligatorio
segmentPresetstring | nullobligatorio
customerIdsstring (uuid)[] | nullobligatorio
Aviso directo a estos clientes.
titlestring | nullobligatorio
textstringobligatorio
status"draft" | "scheduled" | "sending" | "sent" | "cancelled" | "failed"obligatorio
origin"manual" | "automation" | "ai" | "mcp" | "api"obligatorio
scheduledAtstring (date-time) | nullobligatorio
sentAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
get/campaigns/quotaCupo del mes
Plan mínimo: ProPermiso: campaigns:read

Respuesta 200 · CampaignQuota

planstringobligatorio
monthstringobligatorio
maxinteger | nullobligatorio
usedintegerobligatorio
remaininginteger | nullobligatorio
timezonestringobligatorio
get/segmentsSegmentos disponibles
Plan mínimo: ProPermiso: campaigns:read

Respuesta 200 · SegmentList

segmentsobject[]obligatorio
presetsobject[]obligatorio
get/campaigns/{id}Campaña y reporte
Plan mínimo: ProPermiso: campaigns:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · CampaignDetail

idstring (uuid)obligatorio
programIdstring (uuid) | nullobligatorio
segmentIdstring (uuid) | nullobligatorio
segmentPresetstring | nullobligatorio
customerIdsstring (uuid)[] | nullobligatorio
Aviso directo a estos clientes.
titlestring | nullobligatorio
textstringobligatorio
status"draft" | "scheduled" | "sending" | "sent" | "cancelled" | "failed"obligatorio
origin"manual" | "automation" | "ai" | "mcp" | "api"obligatorio
scheduledAtstring (date-time) | nullobligatorio
sentAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
reportobjectobligatorio
post/campaigns/{id}/sendMandar ahora

Pasa por el revisor, el consentimiento, el cupo del plan y el tope de 3 avisos por pase cada 24 h.

Errores: campaign_review_failed, campaign_no_recipients, campaign_limit_reached.

Plan mínimo: ProPermiso: campaigns:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · Campaign

idstring (uuid)obligatorio
programIdstring (uuid) | nullobligatorio
segmentIdstring (uuid) | nullobligatorio
segmentPresetstring | nullobligatorio
customerIdsstring (uuid)[] | nullobligatorio
Aviso directo a estos clientes.
titlestring | nullobligatorio
textstringobligatorio
status"draft" | "scheduled" | "sending" | "sent" | "cancelled" | "failed"obligatorio
origin"manual" | "automation" | "ai" | "mcp" | "api"obligatorio
scheduledAtstring (date-time) | nullobligatorio
sentAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
post/campaigns/{id}/scheduleProgramar

Errores: invalid_schedule, campaign_limit_reached.

Plan mínimo: ProPermiso: campaigns:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Cuerpo ScheduleCampaignInput

sendAtstringobligatorio
Hora local del comercio.

Respuesta 200 · Campaign

idstring (uuid)obligatorio
programIdstring (uuid) | nullobligatorio
segmentIdstring (uuid) | nullobligatorio
segmentPresetstring | nullobligatorio
customerIdsstring (uuid)[] | nullobligatorio
Aviso directo a estos clientes.
titlestring | nullobligatorio
textstringobligatorio
status"draft" | "scheduled" | "sending" | "sent" | "cancelled" | "failed"obligatorio
origin"manual" | "automation" | "ai" | "mcp" | "api"obligatorio
scheduledAtstring (date-time) | nullobligatorio
sentAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
post/campaigns/{id}/cancelCancelar una programada

Errores: campaign_not_cancellable.

Plan mínimo: ProPermiso: campaigns:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · Campaign

idstring (uuid)obligatorio
programIdstring (uuid) | nullobligatorio
segmentIdstring (uuid) | nullobligatorio
segmentPresetstring | nullobligatorio
customerIdsstring (uuid)[] | nullobligatorio
Aviso directo a estos clientes.
titlestring | nullobligatorio
textstringobligatorio
status"draft" | "scheduled" | "sending" | "sent" | "cancelled" | "failed"obligatorio
origin"manual" | "automation" | "ai" | "mcp" | "api"obligatorio
scheduledAtstring (date-time) | nullobligatorio
sentAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio

Estadísticas

get/statsResumen del período
Plan mínimo: ProPermiso: stats:read

Parámetros

days (query)number
7, 30 o 90.

Respuesta 200 · Stats

periodobjectobligatorio
kpisobjectobligatorio
visitsByDayobject[]obligatorio

Webhooks

get/webhook-endpointsListar webhooks
Plan mínimo: ProPermiso: webhooks:read

Respuesta 200 · WebhookEndpointList

dataWebhookEndpoint[]obligatorio
post/webhook-endpointsCrear un webhook

Devuelve el secret para verificar la firma (una sola vez). Cada evento pide su scope de lectura: customer.* → customers:read; el resto → cards:read.

Errores: webhook_url_not_allowed, webhook_limit_reached.

Plan mínimo: ProPermiso: webhooks:writeIdempotency-Key

Cuerpo CreateWebhookEndpointInput

urlstring (uri)obligatorio
URL HTTPS de un host público.
events"customer.created" | "card.created" | "card.stamped" | "card.points_changed" | "card.balance_changed" | "card.adjusted" | …[]obligatorio
descriptionstring

Respuesta 201 · WebhookEndpointWithSecret

idstring (uuid)obligatorio
urlstringobligatorio
descriptionstring | nullobligatorio
events"customer.created" | "card.created" | "card.stamped" | "card.points_changed" | "card.balance_changed" | "card.adjusted" | …[]obligatorio
enabledbooleanobligatorio
disabledReason"manual" | "failures" | "key_revoked" | "plan" | nullobligatorio
manual, failures, key_revoked (revocaron su clave o su dueño ya no lo es) o plan (pausado hasta que el plan vuelva a incluir webhooks).
consecutiveFailuresintegerobligatorio
lastSuccessAtstring (date-time) | nullobligatorio
lastFailureAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
secretstring | nullobligatorio
Secreto para firmar. Se muestra una sola vez: null en una respuesta repetida (rotalo desde el panel).
noticestring
get/webhook-endpoints/{id}Obtener un webhook
Plan mínimo: ProPermiso: webhooks:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · WebhookEndpoint

idstring (uuid)obligatorio
urlstringobligatorio
descriptionstring | nullobligatorio
events"customer.created" | "card.created" | "card.stamped" | "card.points_changed" | "card.balance_changed" | "card.adjusted" | …[]obligatorio
enabledbooleanobligatorio
disabledReason"manual" | "failures" | "key_revoked" | "plan" | nullobligatorio
manual, failures, key_revoked (revocaron su clave o su dueño ya no lo es) o plan (pausado hasta que el plan vuelva a incluir webhooks).
consecutiveFailuresintegerobligatorio
lastSuccessAtstring (date-time) | nullobligatorio
lastFailureAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
patch/webhook-endpoints/{id}Editar o reactivar un webhook

Los eventos piden el mismo scope de lectura que al crear.

Errores: webhook_url_not_allowed.

Plan mínimo: ProPermiso: webhooks:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Cuerpo UpdateWebhookEndpointInput

urlstring (uri)
URL HTTPS de un host público.
events"customer.created" | "card.created" | "card.stamped" | "card.points_changed" | "card.balance_changed" | "card.adjusted" | …[]
descriptionstring | null
enabledboolean

Respuesta 200 · WebhookEndpoint

idstring (uuid)obligatorio
urlstringobligatorio
descriptionstring | nullobligatorio
events"customer.created" | "card.created" | "card.stamped" | "card.points_changed" | "card.balance_changed" | "card.adjusted" | …[]obligatorio
enabledbooleanobligatorio
disabledReason"manual" | "failures" | "key_revoked" | "plan" | nullobligatorio
manual, failures, key_revoked (revocaron su clave o su dueño ya no lo es) o plan (pausado hasta que el plan vuelva a incluir webhooks).
consecutiveFailuresintegerobligatorio
lastSuccessAtstring (date-time) | nullobligatorio
lastFailureAtstring (date-time) | nullobligatorio
createdAtstring (date-time)obligatorio
updatedAtstring (date-time)obligatorio
delete/webhook-endpoints/{id}Borrar un webhook
Plan mínimo: ProPermiso: webhooks:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 204

post/webhook-endpoints/{id}/testMandar un evento de prueba
Plan mínimo: ProPermiso: webhooks:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 201 · WebhookDelivery

idstring (uuid)obligatorio
endpointIdstring (uuid)obligatorio
eventIdstringobligatorio
eventTypestringobligatorio
status"pending" | "succeeded" | "failed"obligatorio
attemptsintegerobligatorio
responseStatusinteger | nullobligatorio
errorstring | nullobligatorio
livemodebooleanobligatorio
createdAtstring (date-time)obligatorio
lastAttemptAtstring (date-time) | nullobligatorio
deliveredAtstring (date-time) | nullobligatorio
get/webhook-endpoints/{id}/deliveriesEntregas recientes
Plan mínimo: ProPermiso: webhooks:read

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.
limit (query)integer
Tamaño de página (1–100).
cursor (query)string
El nextCursor de la página anterior.

Respuesta 200 · WebhookDeliveryList

dataWebhookDelivery[]obligatorio
nextCursorstring | nullobligatorio
Pasalo como cursor para seguir.
post/webhook-deliveries/{id}/retryReenviar una entrega
Plan mínimo: ProPermiso: webhooks:writeIdempotency-Key

Parámetros

id (path)string (uuid)obligatorio
Id del recurso.

Respuesta 200 · WebhookDelivery

idstring (uuid)obligatorio
endpointIdstring (uuid)obligatorio
eventIdstringobligatorio
eventTypestringobligatorio
status"pending" | "succeeded" | "failed"obligatorio
attemptsintegerobligatorio
responseStatusinteger | nullobligatorio
errorstring | nullobligatorio
livemodebooleanobligatorio
createdAtstring (date-time)obligatorio
lastAttemptAtstring (date-time) | nullobligatorio
deliveredAtstring (date-time) | nullobligatorio