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
- Open Brand & social accounts → API & MCP (/app/settings/api), go to Webhooks, and click Add webhook.
- Enter the Endpoint URL. It must be
https://and a public address; private or internal addresses (e.g.localhostor192.168.x.x) are rejected. Choose the Events, then click Add webhook. - Click Copy secret to save the signing secret (
whsec_…). The secret is shown only once. - 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>.
- Read the raw body exactly as received. Don't parse it and turn it back into text.
- Reject the delivery if
X-Posto-Timestampdiffers from your server clock by more than 5 minutes (300 seconds). - 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?
Artikel terkait
Belum ketemu jawabannya?
Tim support siap membantu. Sebutkan judul carousel atau jam kejadian supaya kami cepat menemukannya.
