Tikin · Docs
Guías

Webhooks

Firma HMAC, reintentos, y por qué el polling sigue siendo tu red.

Registrar el endpoint

Dinos a dónde avisarte y qué eventos te importan:

curl -X POST https://api.tikin.is/v1/webhook_endpoints \
  -H "Authorization: Bearer tk_live_…" \
  -H "Idempotency-Key: $(uuidgen | tr 'A-Z' 'a-z')" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://tuapp.com/hooks/tikin",
    "events": ["payout.completed", "payout.failed", "payout.returned", "bonus_batch.ready"]
  }'

La respuesta trae el secret de firma, que se muestra UNA sola vez. Guárdalo en tu almacén de secretos ya — no se puede volver a consultar.

Los eventos disponibles: transfer.completed · payout.completed · payout.failed · payout.returned · bonus_batch.ready · bonus_batch.completed · account.verified.

Verificar la firma

Cada entrega llega firmada con HMAC-SHA256 en el header Tikin-Signature. Verifica ANTES de procesar — un webhook sin verificar es un endpoint público que mueve tu lógica de dinero:

import hmac, hashlib

def verificar(secret: str, cuerpo_crudo: bytes, firma_recibida: str) -> bool:
    esperada = hmac.new(secret.encode(), cuerpo_crudo, hashlib.sha256).hexdigest()
    return hmac.compare_digest(esperada, firma_recibida)

Usa el cuerpo crudo del request (bytes, tal como llegó), no el JSON re-serializado — cualquier reordenamiento de llaves rompe la firma.

Reintentos

Responde 2xx rápido (encola y procesa aparte). Si no respondes 2xx, reintentamos con backoff — lo que implica que puedes recibir el mismo evento dos veces: procesa por id de evento, idempotente, igual que nos exiges a nosotros.

El polling es tu red de seguridad

Los webhooks avisan; no son la fuente de verdad. Tu endpoint puede estar caído justo cuando el payout falló. La regla: todo estado que te importe debe poder reconstruirse por polling (GET /v1/payouts/{id}, GET /v1/bonus_batches/{id}). Un cron que revisa lo que lleva mucho tiempo "en vuelo" te salva el día que el webhook no llegó — y ese día llega.

Si dudas, lee /v1/events — el log es la verdad

Todo evento que te enviamos (y los que tu endpoint se perdió) queda en el log de eventos: consultable, paginado por cursor, filtrable por tipo y fecha. Es la pieza de reconciliación definitiva:

curl "https://api.tikin.is/v1/events?type=payout.failed&created_at\[gte\]=2026-09-08T00:00:00Z" \
  -H "Authorization: Bearer tk_live_…"

El patrón: un cron recorre el log desde el último cursor procesado y compara contra lo que tus webhooks ya aplicaron. Nada se pierde, aunque tu endpoint haya estado caído un día entero. Y para volver a recibir UNA entrega puntual, POST /v1/events/{event_id}/redeliver la reenvía firmada, con el mismo id — tu procesamiento idempotente la absorbe sin duplicar nada.

On this page