Ir al contenido

Webhooks

Una URL HTTPS por workspace. Sin events recibes todos. El secreto de firma solo se devuelve al crearlo: guárdalo.

Ventana de terminal
curl -X PUT "https://api.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/webhooks/crier",
"events": [
"post.published",
"post.failed",
"account.disconnected"
]
}'
Evento Cuándo data
post.scheduled Se programó o entró en la cola post
post.published Salió en todas las redes post
post.partial Salió en algunas y falló en otras post
post.failed No salió en ninguna post
post.cancelled Se canceló post
post.removed Se retiró de una red post
post.rejected Se rechazó en la revisión y volvió a borrador post
post.recycled Se creó una copia reciclada post (la copia), recycledFrom
account.connected Se conectó una cuenta account
account.disconnected Se desconectó o hay que reconectarla account
message.received (pronto) Alguien escribió un mensaje directo accountId, conversationId, message
comment.received Alguien comentó una publicación accountId, postId, comment
review.received (pronto) Llegó una reseña nueva (Google Business) accountId, review
Cuerpo
{
"id": "evt_9a8s7d",
"type": "post.published",
"createdAt": "2026-10-23T10:00:05.000Z",
"data": {
"post": {
"id": "pst_7q1w0e",
"status": "published",
"targets": [
{ "accountId": "acc_3k9x2m", "platform": "instagram", "status": "published", "url": "https://www.instagram.com/p/…" }
]
}
}
}

Cada envío lleva Crier-Event, Crier-Event-Id y Crier-Signature: t=<segundos>,v1=<hex>. v1 es el HMAC-SHA256 de <t>.<cuerpo> con tu secreto. Compáralo con el cuerpo sin parsear y rechaza firmas de hace más de 5 minutos.

Node
import { createHmac, timingSafeEqual } from 'node:crypto';
export const verifyCrierSignature = (rawBody, header, secret) => {
const { t, v1 } = Object.fromEntries(header.split(',').map((part) => part.split('=')));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
};
Python
import hmac, hashlib, time
def verify_crier_signature(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(part.split("=", 1) for part in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
  • Responde con un 2xx en menos de 10 segundos. Haz el trabajo pesado después.
  • Si fallas, reintentamos varias veces con espera creciente.
  • Un mismo evento puede llegar más de una vez: usa Crier-Event-Id para no procesarlo dos veces.

© 2026 Crier by TWOFACES ·usecrier.com ·Panel ·soporte@twofacesco.com