Guides
Webhooks
Get told when something happens instead of polling. Register an endpoint and PostLake POSTs an event to it when a post publishes, fails, or an account connects. Ideal for scheduled posts and async platforms.
Register an endpoint
Give PostLake a URL and the events you care about. You get back a WebhookEndpoint with a secret used to verify deliveries.
curl -X POST https://api.postlake.dev/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/hooks/postlake",
"events": ["post.published", "post.failed"]
}'Event types
| Event | Fires when |
|---|---|
post.published | Every target of a post has published. |
post.partial | Some targets published, some failed. |
post.failed | No target published. |
post.processing | A post moved to processing (async platforms). |
account.connected | A social account finished connecting. |
The delivery
PostLake POSTs a JSON body with the event type and the affected resource (the full Post for post.* events), so you can act without a follow-up API call.
{
"type": "post.published",
"data": { "id": "post_a1b2c3", "state": "published", "targets": [ … ] }
}Verify the signature
Every delivery carries a postlake-signature header of the form t=<unix-seconds>,v1=<hex>. The v1 value is an HMAC-SHA256 of <t>.<raw-body> keyed with your endpoint secret. Verify it before trusting the payload. This proves the request really came from PostLake and (with a timestamp tolerance) blocks replays.
Verify the raw body, exactly as received. Don't parse and re-serialize the JSON first, or the bytes (and the signature) change.
With the SDK it's one call:
import { verifyWebhookSignature } from "postlake";
// in your handler. Pass the RAW request body
const ok = await verifyWebhookSignature(
endpointSecret, // the secret returned by webhooks.create()
rawBody, // exact bytes received
req.headers["postlake-signature"], // the signature header
{ toleranceSec: 300 }, // reject deliveries older than 5 min (optional)
);
if (!ok) return res.status(400).end();Or without the SDK, in plain Node:
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(secret, rawBody, header) {
const { t, v1 } = Object.fromEntries(header.split(",").map(kv => kv.split("=")));
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected), b = Buffer.from(v1);
return a.length === b.length && timingSafeEqual(a, b);
}Respond 2xx quickly once verified; failed deliveries are retried with backoff.
Managing endpoints
List your endpoints with GET /v1/webhooks and remove one with DELETE /v1/webhooks/{id}. See the API reference for the exact shapes.