postmatic

Webhooks

Receba um POST assinado quando um post é agendado ou termina, verifique a assinatura, trate as novas tentativas e consulte o histórico de entregas.

Em vez de consultar GET /v1/posts/:id em laço, cadastre uma URL e a Postmatic avisa.

Eventos

EventoQuando
post.scheduledUm agendamento foi aceito (POST /v1/posts com scheduledFor, ou retry agendado).
post.publishedTodos os destinos publicaram.
post.partialPelo menos um destino publicou e pelo menos um falhou.
post.failedTodos os destinos falharam (inclusive agendamento perdido, MISSED).

Um post agendado emite post.scheduled e depois um evento final. Um post imediato emite só o final. Cancelar pela API não emite nada. Um POST /v1/posts/:id/retry gera um novo evento final quando terminar.

Cadastrar

POST /v1/notifications
curl -X POST https://api.uat.postmatic.dev/v1/notifications \
  -H "x-access-key: pm_live_…" \
  -H "content-type: application/json" \
  -d '{ "eventTypes": ["post.published", "post.partial", "post.failed"], "webhook": { "url": "https://seu-app.com/hooks/postmatic" } }'

A resposta traz webhook.secret (whsec_…) uma única vez. Guarde-o. profileId restringe aos posts de um profile; onlyScheduledPosts: true manda eventos finais só de posts que foram agendados.

Teste o destino antes ou depois de salvar com POST /v1/notifications/test ({ "notificationId": "ntf_…" } ou { "webhook": { "url": "…" } }).

Verificar a assinatura

Cada entrega é um POST com Content-Type: application/json e estes headers:

HeaderValor
X-Postmatic-Event-IdId do evento (evt_…). Use como chave de deduplicação.
X-Postmatic-Event-TypeEx.: post.published.
X-Postmatic-TimestampUnix timestamp em segundos.
X-Postmatic-Signaturesha256= + HMAC-SHA256 hex de <timestamp>.<corpo cru>.
Node
import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(secret: string, headers: Record<string, string>, rawBody: string): boolean {
  const ts = headers['x-postmatic-timestamp'];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // 5 min de tolerância
  const expected = `sha256=${createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex')}`;
  const given = headers['x-postmatic-signature'] ?? '';
  return given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}

Assine sobre o corpo cru (não reserialize o JSON). Responda 2xx em menos de 10 segundos e processe depois.

Payload

json
{
  "version": "2026-09-01",
  "id": "evt_…",
  "type": "post.published",
  "createdAt": "2026-09-09T12:00:00.000Z",
  "projectId": "proj_…",
  "profileId": null,
  "data": {
    "post": {
      "id": "post_…", "status": "published", "content": "Novidade no ar.",
      "scheduledFor": null, "publishedAt": "2026-09-09T12:00:00.000Z",
      "mediaItems": [{ "type": "image", "url": "https://…/foto.jpg" }],
      "links": { "api": "https://api.uat.postmatic.dev/v1/posts/post_…" }
    },
    "platforms": [{
      "platform": "instagram", "integrationId": "int_…", "profileId": null,
      "status": "published", "platformPostId": "1790…", "platformPostUrl": "https://www.instagram.com/p/…/",
      "publishedAt": "2026-09-09T12:00:00.000Z", "errorCode": null, "errorMessage": null, "warningMessage": null
    }]
  }
}

Novas tentativas

Sem 2xx em 10 segundos, a Postmatic tenta de novo depois de 30 s e de 2 min (3 tentativas no total), com o mesmo corpo e o mesmo id. Depois disso a entrega fica failed no histórico. Duplicatas são possíveis: deduplique pelo id.

Histórico

GET /v1/notifications/:id/deliveries lista cada evento entregue à assinatura, com status (pending, delivered, failed), attempt, responseStatus e error.

Webhooks — Documentação Postmatic