Webhooks
Webhooks notify you in real time of events on your connected accounts. No need to poll the API.
Create a webhook
POST /v1/webhooks
{
"url": "https://your-app.com/webhooks/pepe",
"events": [
"post.published",
"post.failed",
"inbox.message.received",
"inbox.comment.received"
]
}
Response:
{
"id": "whk_xxx",
"url": "https://your-app.com/webhooks/pepe",
"secret": "whsec_xxxxx",
"status": "active"
}
Signature verification
Each webhook is signed with HMAC-SHA256. Verify it server-side:
import crypto from "crypto";
function verifyWebhook(rawBody: string, signature: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Express
app.post("/webhooks/pepe", (req, res) => {
const sig = req.headers["x-pepe-signature"] as string;
if (!verifyWebhook(req.rawBody, sig, process.env.PEPE_WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
// Processing...
res.status(200).send("OK");
});
Available events
| Family | Events |
|---|---|
| Posts | post.published, post.failed, post.scheduled, post.unpublished |
| Inbox | inbox.message.received, inbox.comment.received, inbox.review.received, inbox.mention.received |
| Accounts | account.connected, account.disconnected, account.health_changed |
| Ads | ads.campaign.started, ads.campaign.ended, ads.budget_exhausted |
| Calls | call.incoming, call.completed, call.recording.ready |
whatsapp.message.received, whatsapp.template.approved | |
| Phone numbers | phone_number.purchased, phone_number.ported |
Idempotency
Each webhook includes a unique eventId (X-Pepe-Event-Id). Keep it for 24h to avoid duplicates.
{
"eventId": "evt_01HXXXXXX",
"type": "post.published",
"data": { "postId": "post_xxx", "platforms": ["twitter"] },
"createdAt": "2026-07-13T10:00:00Z"
}
Retries
Webhooks are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | +30s |
| 3 | +2 min |
| 4 | +10 min |
| 5 | +1 h |
| 6 | +6 h |
| 7 | +24 h (last) |
If your server returns a non-2xx code after 7 attempts, the webhook is marked failed.
Delivery logs
All attempts are visible in Dashboard > Webhooks > Delivery Logs. You can replay an event manually.
Test
pepe webhooks send-test --event post.published --url https://your-app.com/webhooks/pepe