Ir al contenido

Webhooks

Los webhooks te permiten enterarte de eventos importantes en tu workspace sin pollear. Cuando un usuario se registra en tu instancia, te mandamos un POST a tu endpoint con la info. Vos respondés 2xx y seguís.

Ventana de terminal
curl -X POST https://api.prysmid.com/v1/workspaces/$WS/webhooks \
-H "Authorization: Bearer $TOKEN" \
-d '{
"url": "https://yourapp.com/hooks/prysmid",
"events": ["user.created", "user.deleted", "session.started"]
}'

Respuesta:

{
"id": "wh_abc123",
"url": "https://yourapp.com/hooks/prysmid",
"secret": "whsec_29uifd89...", // mostrado UNA vez; guardalo
"events": ["user.created", "user.deleted", "session.started"],
"created_at": "2026-04-28T10:00:00Z"
}

Cada delivery viene con header Prysmid-Signature: t=<unix_ts>,v1=<hmac_sha256>. La firma se computa sobre <unix_ts>.<raw_body> con tu webhook secret como key HMAC.

import hmac, hashlib, time
def verify(secret, signature_header, raw_body, max_age_seconds=300):
parts = dict(p.split("=", 1) for p in signature_header.split(","))
ts, sig = int(parts["t"]), parts["v1"]
if abs(time.time() - ts) > max_age_seconds:
raise ValueError("timestamp too old (replay protection)")
expected = hmac.new(secret.encode(), f"{ts}.{raw_body}".encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
raise ValueError("invalid signature")
EventoCuándo dispara
user.createdNuevo usuario completó signup en tu instance.
user.updatedCambio de email, nombre, attributes.
user.deletedUsuario borrado por admin o por self-service.
session.startedLogin exitoso.
session.endedLogout o expiración.
tenant.createdNuevo tenant creado en tu workspace.
tenant.deletedTenant borrado.
plan.changedTu workspace cambió de plan (Free→Pro etc).
subscription.past_duePago falló; estás en grace period.
mau.threshold_warningCruzaste 80% / 95% / 100% del MAU incluido.
signups_blockedSpending cap alcanzado; nuevos signups bloqueados.
{
"id": "evt_abc123",
"type": "user.created",
"workspace_id": "ws_xyz",
"tenant_id": "tn_acme",
"created_at": "2026-04-28T10:00:00Z",
"data": {
"user_id": "294857...",
"email": "alice@acme.com",
"name": "Alice",
"via_idp": "google"
}
}

Si tu endpoint responde no-2xx (o no responde en 10s), reintentamos con backoff exponencial:

  • 1m, 5m, 30m, 2h, 6h, 12h, 24h, 48h.
  • Después de 48h sin éxito, marcamos el evento como failed_permanent y lo podés ver en Settings → Webhooks → Failed.

Idempotencia: usá el id del evento como deduplication key. Un mismo evento puede entregarse varias veces (al-menos-una-vez, no exactly-once).

Si tu endpoint falla más del 5% del tráfico durante 30 minutos, te mandamos un email de aviso a los owners del workspace. Si sigue caído por 24h, pausamos las entregas (no las eventos — quedan encolados) hasta que lo reactives manualmente desde el dashboard.

  • Tokens emitidos (access_token / id_token): no los exponemos por webhook. Riesgo de filtrar credenciales activas.
  • Passwords: nunca hashed, nunca plain. Ni siquiera el hash sale de la instance.
  • Eventos del plano de control en realtime: cosas como “miembro del workspace cambió rol” — disponibles en audit log, no por webhook (frecuencia muy baja, no justifica push).