Lewati ke konten

Webhooks: automatic updates from Posto

Terakhir diperbarui

Di artikel ini

Webhooks let Posto notify your server or automation tool (e.g. n8n) whenever something happens, such as a carousel finishing or a post going live. Webhooks live on the same page as API keys, so they need API & MCP access. See API and MCP.

Add a webhook

  1. Open Brand & social accounts → API & MCP (/app/settings/api), go to Webhooks, and click Add webhook.
  2. Enter the Endpoint URL. It must be https:// and a public address; private or internal addresses (e.g. localhost or 192.168.x.x) are rejected. Choose the Events, then click Add webhook.
  3. Click Copy secret to save the signing secret (whsec_…). The secret is shown only once.
  4. Click Send ping to test it. The result appears under History.

Available events: carousel.ready, carousel.failed, image.ready, post.published, post.failed, credits.low, approval.decided, series.paused (a recurring schedule was paused), and series.ended (a recurring schedule finished or was ended). Up to 10 webhooks per workspace.

What Posto sends

Posto sends a JSON POST like this:

{
  "id": "b2f6c1e0-…",
  "type": "post.published",
  "createdAt": "2026-10-17T12:30:41Z",
  "workspaceId": "0b6e2d14-…",
  "apiVersion": "v1",
  "data": { "scheduleId": "…", "carouselId": "…", "platform": "instagram", "permalink": "…" }
}

Headers included: X-Posto-Event, X-Posto-Delivery, X-Posto-Timestamp (Unix seconds), and X-Posto-Signature. Reply 2xx within 10 seconds; redirects are not followed. The same delivery may arrive more than once, so skip event ids you have already processed.

Verify the signature

X-Posto-Signature contains v1=<hex>: an HMAC-SHA256 with your webhook secret over the text <X-Posto-Timestamp>.<raw body>.

  1. Read the raw body exactly as received. Don't parse it and turn it back into text.
  2. Reject the delivery if X-Posto-Timestamp differs from your server clock by more than 5 minutes (300 seconds).
  3. Compute the HMAC and compare it with every v1= value in the header using a constant-time comparison (timingSafeEqual).

Node.js (Express) example:

import crypto from 'node:crypto'
import express from 'express'

const app = express()
const SECRET = process.env.POSTO_WEBHOOK_SECRET // whsec_...

app.post('/webhook/posto', express.raw({ type: 'application/json' }), (req, res) => {
  const ts = req.get('X-Posto-Timestamp') || ''
  const header = req.get('X-Posto-Signature') || ''
  const raw = req.body // Buffer: raw body, not parsed

  if (!/^[0-9]+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
    return res.status(400).send('stale')
  }
  const expected = crypto.createHmac('sha256', SECRET).update(ts + '.').update(raw).digest()
  const ok = header.split(',').some((part) => {
    const m = /^v1=([0-9a-f]{64})$/.exec(part.trim())
    return m !== null && crypto.timingSafeEqual(Buffer.from(m[1], 'hex'), expected)
  })
  if (!ok) return res.status(401).send('bad signature')

  const event = JSON.parse(raw.toString('utf8'))
  res.status(200).end() // reply fast, process event.id in the background (skip ids already seen)
})

Failures, auto-disable, and secret rotation

  • Failed deliveries are retried 6 times (1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours, 24 hours). Every attempt is listed under History.
  • If 3 deliveries in a row fail and the failures last 3 days, the webhook is turned off automatically and the workspace owner and admins get an email. Fix the endpoint, then click Turn back on.
  • Rotate secret (in the more actions menu) creates a new secret. For 24 hours the header carries two signatures (v1=<new>,v1=<old>), giving you time to update the secret on your server.

Still stuck? Contact [email protected].

Apakah artikel ini membantu?

Belum ketemu jawabannya?

Tim support siap membantu. Sebutkan judul carousel atau jam kejadian supaya kami cepat menemukannya.

[email protected]

Kembali ke API & integrations