Documentación de Rekomi
Para desarrolladores
Desarrolladores

Registrar eventos del embudo

Informa de los pasos que alcanza un cliente referido después del clic, como una solicitud, una aprobación o una cuenta con fondos, con una llamada firmada de servidor a servidor por cada paso. Cada paso puede pagarle al afiliado un importe fijo y cuenta para los límites de volumen.

Un evento del embudo es un paso con nombre que alcanza un cliente referido después del clic: una solicitud iniciada, una solicitud aprobada, una cuenta con fondos. Defines los pasos en la campaña y tu backend informa de cada uno con un postback firmado. Rekomi registra quién refirió al cliente, le paga al afiliado si el paso lleva un pago y muestra el embudo completo por afiliado.

Los eventos conviven con las ventas y los leads. Nunca cambian tus recuentos de ventas, leads o clics, y funcionan tengas o no una pasarela de pago conectada.

Plan necesario: Starter o superior. Las cuentas en periodo de prueba siempre se aceptan.

Define tus eventos

Abre la campaña, ve a Comisión y añade tus pasos en Eventos del embudo. Cada evento tiene:

  • un nombre (por ejemplo, Application approved),
  • una clave, que se crea a partir del nombre (application_approved). La clave es lo que envía tu postback y nunca cambia. Un nombre sin letras latinas ni dígitos recibe una clave como event_3, que se muestra junto al nombre,
  • un pago por evento opcional, un importe fijo en tu moneda principal. Déjalo vacío si solo quieres registrar el paso.

El orden de la lista es el orden de las columnas en el informe del embudo. Una campaña puede registrar hasta 20 eventos.

Endpoint

POST /api/tracking/event

Producción: https://api.rekomi.com/api/tracking/event (también disponible como /api/v1/tracking/event).

La autenticación es la misma que en el postback de ventas S2S: tu clave de API en Authorization: Bearer rk_live_*, más una cabecera X-Rekomi-Signature con un HMAC-SHA256 de {unix-seconds}.{raw-body} calculado con el secreto de firma de la clave. Reutiliza la misma función de firma. La marca de tiempo debe estar a menos de 300 segundos de la hora actual, y la clave necesita acceso de escritura.

Cuerpo de la petición

{
  "event": "application_approved",
  "externalEventId": "app_58213_approved",
  "affiliateSlug": "jane-recommends",
  "customerId": "cust_58213",
  "customerEmail": "user@example.com",
  "amountCents": 2500000,
  "currency": "USD",
  "subId": "newsletter"
}
  • event (obligatorio): la clave de uno de los eventos de la campaña.
  • externalEventId (obligatorio): tu id único para esta ocurrencia, de hasta 128 caracteres. Es único en toda tu cuenta, así que un reintento con el mismo id es seguro y siempre devuelve el primer registro, envíe lo que envíe el reintento.
  • affiliateSlug (opcional): el afiliado que refirió al cliente. Envíalo en el primer paso. En los pasos siguientes puedes omitirlo y enviar solo el cliente (consulta Enviar el afiliado una sola vez).
  • customerId (opcional): tu propio id del cliente. Es lo que une los pasos de un mismo cliente.
  • customerEmail (opcional): el correo del cliente, que se usa igual cuando no tienes un id de cliente.
  • programId (opcional): el id de la campaña. Si lo envías junto con affiliateSlug, tiene que ser la campaña de ese afiliado. Si lo envías sin slug, limita la búsqueda del cliente a esa campaña. Cuando un afiliado promociona más de una de tus campañas, envía el slug del enlace de la campaña a la que te refieres.
  • amountCents (opcional): un valor para el paso, en unidades menores de currency, por ejemplo un importe con el que se dotó la cuenta. Se guarda para tus informes y no cambia el pago.
  • currency (opcional): código ISO 4217 para amountCents y para commissionCents cuando lo envías. Por defecto, tu moneda principal.
  • commissionCents (opcional): lo que esta ocurrencia le paga al afiliado, cuando es tu backend quien decide el importe. Sustituye el pago configurado del evento solo para esta ocurrencia. Envía 0 para registrar el paso sin pagar.
  • subId (opcional): la etiqueta de canal que llevaba la visita del cliente.
  • occurredAt (opcional): cuándo ocurrió el paso (ISO 8601), si informas de él con retraso. Un valor sin zona horaria se interpreta como UTC. No puede estar en el futuro ni tener más de cinco años.

Envía en cada llamada affiliateSlug o un cliente (customerId o customerEmail).

Enviar el afiliado una sola vez

La mayoría de los backends conocen al afiliado que refirió al cliente cuando este llega por primera vez, y solo después tienen su propio id de cliente. Por eso Rekomi identifica al afiliado en este orden:

  1. affiliateSlug, cuando lo envías.
  2. El evento anterior más reciente con el mismo customerId.
  3. El evento anterior más reciente con el mismo customerEmail.
  4. Un lead registrado con ese correo en los últimos 90 días.

Así, una integración típica envía el slug con el primer paso y un customerId estable con todos los pasos:

{ "event": "lead", "externalEventId": "c58213_lead", "affiliateSlug": "jane-recommends", "customerId": "cust_58213" }
{ "event": "funded", "externalEventId": "c58213_funded", "customerId": "cust_58213" }

Respuesta

Un evento registrado por primera vez:

{ "ok": true, "eventId": "0b6f...", "conversionId": "c0nv...", "commissionCents": 5000, "overCap": false }
  • conversionId viene informado cuando el paso le pagó al afiliado. A partir de ahí, el dinero es una comisión normal: aparece en la página Conversiones como bono, espera a que termine la retención por reembolso y se paga con todo lo demás.
  • overCap es true cuando el afiliado ya había alcanzado un límite de volumen configurado para retener. El paso se registra igualmente. Si lleva un pago, conversionId apunta a una comisión retenida (estado Invalidated, commissionCents a 0 en esta respuesta) que se paga cuando la validas en la página Conversiones.

Un evento que ya estaba registrado:

{ "ok": true, "deduped": true, "eventId": "0b6f..." }

Hay dos casos que cuentan como ya registrados: el mismo externalEventId, y el mismo evento para el mismo cliente. Un cliente se aprueba una sola vez, así que un segundo application_approved para el mismo customerId devuelve el primero.

Errores

409 external_event_id_reused significa que el externalEventId ya se usó para otro evento: usa un id por paso, por ejemplo el id del cliente más la clave del evento. Un 401 con el cuerpo vacío significa que se rechazó la clave, la firma o la marca de tiempo. 402 plan_tier_required significa que la cuenta está por debajo de Starter y no está en periodo de prueba. 413 significa que el cuerpo supera los 8,192 bytes, 429 significa que envías más rápido de lo que permite el límite de peticiones y 500 persist_failed significa que el evento no se pudo guardar, así que reinténtalo con el mismo externalEventId. Todo lo demás es un 400 con un código error:

errorCausa
invalid_bodyEl cuerpo no es JSON válido
event_required, invalid_eventFalta event o no es una clave válida
unknown_eventLa campaña no tiene ningún evento activo con esa clave
external_event_id_required, external_event_id_too_longFalta, o tiene más de 128 caracteres
customer_id_too_long, customer_email_too_longTiene más de 255 y 320 caracteres, respectivamente
affiliate_slug_or_customer_requiredNo se envió ni un slug ni un cliente
affiliate_not_foundEl slug no coincide con ningún afiliado de tu cuenta
affiliate_not_resolvedNo se envió slug y ningún evento o lead anterior coincide con el cliente
affiliate_not_activeEl afiliado no está aprobado
program_mismatchprogramId no es la campaña del afiliado
no_active_programLa campaña del afiliado está inactiva o suspendida
amount_out_of_range, invalid_commissionUn importe negativo, o uno de más de 1,000,000,000,000 unidades menores
unsupported_currencycurrency no es un código ISO 4217 admitido
occurred_at_in_future, occurred_at_too_oldoccurredAt está fuera del rango aceptado

Ejemplo

import crypto from "node:crypto";

const BEARER = process.env.REKOMI_API_KEY!;         // rk_live_...
const SIGNING = process.env.REKOMI_SIGNING_SECRET!; // rks_...

async function trackEvent(input: {
  event: string;
  externalEventId: string;
  affiliateSlug?: string;
  customerId?: string;
  customerEmail?: string;
}) {
  const body = JSON.stringify(input); // serialize once: these exact bytes are signed and sent
  const t = Math.floor(Date.now() / 1000);
  const sig = crypto.createHmac("sha256", SIGNING).update(`${t}.${body}`).digest("hex");
  const res = await fetch("https://api.rekomi.com/api/tracking/event", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${BEARER}`,
      "X-Rekomi-Signature": `t=${t},sig=${sig}`,
      "Content-Type": "application/json",
    },
    body,
  });
  if (!res.ok) throw new Error(`Rekomi event failed: ${res.status} ${await res.text()}`);
  return res.json();
}

Consultar los eventos

  • Panel: la pestaña Rendimiento de la campaña muestra la tabla Embudo, con una fila por afiliado y una columna por evento, y una exportación a CSV.
  • API: GET /api/v1/programs/{programId}/funnel devuelve el mismo informe (filtros since, until y affiliateId; format=csv para la tabla). GET /api/v1/funnel-events lista las ocurrencias registradas (programId, affiliateId, event, since, until, take, skip), y GET /api/v1/funnel-events/export.csv las exporta.
  • Webhooks: cada evento registrado dispara event.recorded. Un paso que paga también dispara el conversion.created de siempre.

Conviene saber

  • El importe de un evento que paga es el mismo para todos los afiliados. Para pagar importes distintos a distintos afiliados, envía commissionCents en el postback.
  • Si quitas un evento que ya tiene ocurrencias registradas, se archiva: deja de aceptar postbacks y su historial se queda en el informe. Al quitar un evento también se quitan los límites de volumen definidos sobre él.
  • El pago de un evento es en dinero. En una campaña que recompensa con crédito, los eventos se pueden registrar, pero no pueden llevar un pago.
  • Los eventos no se reembolsan a través de /api/tracking/refund. Para recuperar la comisión de un paso pagado, deniega o ajusta su bono en la página Conversiones.