API operational
Observe & engage

Webhooks

Subscribe to signed events, verify the raw payload, acknowledge quickly, and let PostGate retry outages.

4

Endpoint summary

All operations in this resource, with the minimum accepted key scope.

Method & endpointPurposeScope
GET/api/webhooks

List webhook endpoints

read
POST/api/webhooks

Create a subscription and reveal its secret

full
POST/api/webhooks/{id}/test

Queue a test delivery

full
DELETE/api/webhooks/{id}

Delete a subscription

full
01

Create a subscription

Subscribe only to events your product uses. The signing secret is returned once; save it before discarding the response.
Terminal post eventsPostGate API
curl -X POST https://postgate.studio/api/webhooks \
  -H "Authorization: Bearer $POSTGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.example.com/webhooks/postgate",
    "events": ["post.published", "post.partial", "post.failed"]
  }'
02

Verify the raw request body

PostGate signs <timestamp>.<raw-body> with HMAC-SHA256. Parse the t and v1 values from X-PostGate-Signature, reject stale timestamps, and compare digests in constant time. The stable event ID is also sent as X-PostGate-Event-Id.
Signature shapePostGate API
t=1785254400,v1=4f7c...9a2e
03

Acknowledge before doing work

Verify, persist or enqueue, and return a 2xx response. Delivery is retried when your endpoint times out or returns a non-2xx status. Consumers should deduplicate by the event id.
Test the complete path
Use POST /api/webhooks/{id}/test after deployment and whenever you rotate infrastructure.
04

Use a stable event envelope

Events contain id, type, occurred_at, and a resource-specific data object. Keep unknown fields when relaying events so your own pipeline remains forward compatible.
05

Event catalog

Subscribe any subset of these topics in events[]. post.insights and profile.stats_updated use the same names PostProxy consumers already expect.

  • post.draft / post.scheduled — a post was created in that state.
  • post.published / post.partial / post.failed — a post reached a terminal state.
  • post.insights — a new hourly analytics snapshot exists for a published target: post_id, targets[] (target_id, platform, platform_post_id, metrics), captured_at.
  • profile.connected / profile.disconnected — a profile was connected or disconnected.
  • profile.expiring — a profile’s authorization is nearing expiry.
  • profile.expired — a profile’s token expired with no way to refresh it. Carries reason: "token_expired".
  • profile.reauth_required — a refresh attempt was rejected by the provider (revoked access, changed password, or an authorization error surfaced while publishing). Carries reason: refresh_failed, revoked, or publish_auth_error.
  • profile.stats_updated — a new hourly follower/analytics snapshot exists for a profile: profile_id, platform, followers, follower_delta, metrics, captured_at.
  • stats.updated — PostGate’s generic analytics event, covering both post targets and profiles.
  • comment.created / message.received — inbound engagement arrived.

Both profile.expired and profile.reauth_required fire once per authorization state transition, not on every maintenance sweep; a profile that reconnects and later breaks again fires a new event.