Webhooks
Registrar un webhook
Registra una URL https a la que Sofia llama con un evento JSON firmado, reintentado hasta cinco veces si falla. Secreto visible una vez; máximo 10 webhooks.
Registrar un webhook
Registra una dirección https pública y los eventos deseados. El secreto de firma (whsec_…) solo se muestra en esta respuesta. Una aplicación puede tener hasta 10 webhooks.
curl -X POST https://api.sofia-post.com/api/v1/webhooks \
-H "Authorization: Bearer $SOFIA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url":"https://app.example.com/hooks/sofia","events":["post.published","post.failed"]}'Eventos
| Evento | data |
|---|---|
post.published | postId, establishmentId, platform, publishedAt, permalink |
post.failed | postId, establishmentId, platform, error |
webhook.test | webhookId |
Sofia envía cada evento por POST en formato JSON { id, type, createdAt, data }, con las cabeceras Sofia-Event-Id, Sofia-Event-Type y Sofia-Signature. Solo se anuncian las publicaciones creadas por tu aplicación.
Verificar la firma
Sofia-Signature vale t=<unix time>,v1=<hex>, donde v1 es el HMAC-SHA256 de <t>.<raw body> con tu secreto. Verifícala sobre el cuerpo sin procesar, y rechaza una marca de tiempo antigua:
import { createHmac, timingSafeEqual } from 'node:crypto';
const isSignedBySofia = (header, rawBody, secret) => {
const parts = Object.fromEntries(
(header ?? '').split(',').map((part) => part.trim().split('=', 2)),
);
const timestamp = Number(parts.t);
if (!Number.isInteger(timestamp) || typeof parts.v1 !== 'string') return false;
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest();
const received = Buffer.from(parts.v1, 'hex');
return received.length === expected.length && timingSafeEqual(received, expected);
};Entrega y nuevos intentos
- Una respuesta
2xxentrega el evento. Cualquier otra respuesta, una redirección (nunca seguida) o 10 segundos sin respuesta provocan un nuevo intento tras 1 minuto, 5 minutos, 30 minutos y 2 horas, hasta 5 intentos. - Un mismo evento puede llegar dos veces: deduplica por
Sofia-Event-Id. - Responde rápido y procesa el evento después.
Autorizaciones
AuthorizationstringheaderobligatorioTu clave personal o token de acceso OAuth, enviado como
Bearer <token>.
Cuerpo
urlstringobligatorioLa dirección https a la que llama Sofia. Se rechaza un host que resuelva a una dirección privada, loopback o link-local
eventsstring[]obligatorioLos eventos que recibir
Respuesta
El webhook y su secreto de firma, mostrado una sola vez.
idstringobligatorioIdentificador del webhook.
urlstringobligatorioDirección a la que llama Sofia
eventsstring[]obligatorioLos eventos suscritos
createdAtstring<date-time>obligatorioCuándo se registró el webhook
secretstringobligatorioLa clave HMAC-SHA256 que firma cada envío (
Sofia-Signature). Se muestra solo esta vez