API reference
Subscribe an https endpoint to post and account events; returns the signing secret once.
https://api.betterpost.dev/v1/notificationsSee Webhooks for payloads, headers, signature verification and retries.
| Field | Type | Required | Description |
|---|---|---|---|
channel | string | Yes | "webhook". The email channel is not supported (400 channel_not_supported). |
eventTypes | array | Yes | One or more unique values of post.scheduled, post.published, post.partial, post.failed, account.reauthorization_required, account.disconnected. |
webhook.url | string | Yes | Public https URL, up to 2,048 characters. |
profileId | string or null | No | Only events for this profile's accounts. Default null (all). |
onlyScheduledPosts | boolean | No | Final post events only for scheduled posts. Default false. |
enabled | boolean | No | Default true. |
No other fields are accepted.
curl -s -X POST https://api.betterpost.dev/v1/notifications \
-H "x-access-key: $BETTERPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "webhook",
"eventTypes": ["post.published", "post.partial", "post.failed"],
"webhook": { "url": "https://app.example.com/webhooks/betterpost" }
}'201 Created
{
"success": true,
"notification": {
"id": "ntf_6w2h9k4b1q7s3e8d0f5g2j4l",
"channel": "webhook",
"profileId": null,
"eventTypes": [
"post.published",
"post.partial",
"post.failed"
],
"onlyScheduledPosts": false,
"enabled": true,
"webhook": {
"url": "https://app.example.com/webhooks/betterpost",
"secret": "whsec_9QeM2xT7kL4pZ8vB1nR6cW3yH5jD0sFa"
},
"lastTestAt": null,
"lastTestStatus": null,
"createdAt": "2026-10-21T15:30:00.000Z",
"updatedAt": "2026-10-21T15:30:00.000Z"
}
}Store webhook.secret now. It is never shown in full again.
| Field | Description |
|---|---|
id | Subscription id. |
channel | Always webhook. |
profileId | Profile filter, or null for the whole project. |
eventTypes | Subscribed events. |
onlyScheduledPosts | Final post events only for posts that had a scheduled time. |
enabled | false pauses deliveries. |
webhook.url | Where events are sent. |
webhook.secret | Signing secret: in full only in the create response, masked (whsec_•••• + last 4) everywhere else. |
lastTestAt, lastTestStatus | Always null: tests are sent before saving and are not tracked per subscription. |
createdAt, updatedAt | ISO 8601 timestamps. |
| Status | Code | When |
|---|---|---|
201 | The subscription was created. | |
400 | validation_error | Missing webhook.url or eventTypes, an unknown event, duplicates, or an unknown field. |
400 | invalid_url | The URL is not https or does not resolve to a public address. |
400 | channel_not_supported | channel is email or email settings were sent. |
401 | unauthorized | Missing or unknown API key. |
429 | rate_limited | More than 120 requests per minute. |
404 | not_found | profileId does not exist in this project. |