Skip to content

Webhooks

Webhooks API

Receive real-time notifications when events occur in Flow.

Webhook Events

EventDescription
post.scheduledA post was scheduled
post.publishedA post was successfully published
post.failedA post failed to publish
channel.createdA channel was created
channel.deletedA channel was deleted

Create Webhook

POST /v1/webhooks

Request Body

FieldTypeRequiredDescription
urlstringYesHTTPS URL to receive webhook events
eventsstring[]YesArray of event types to subscribe to
secretstringNoCustom secret for signature verification

Example Request

Terminal window
curl -X POST https://api.flowsocial.app/v1/webhooks \
-H "Authorization: Bearer flow_sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/flow",
"events": ["post.published", "post.failed"]
}'

Example Response

{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/flow",
"events": ["post.published", "post.failed"],
"secret": "whsec_...",
"createdAt": "2024-01-15T10:00:00Z"
}

List Webhooks

GET /v1/webhooks

Example Response

{
"data": [
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/flow",
"events": ["post.published", "post.failed"],
"createdAt": "2024-01-15T10:00:00Z"
}
]
}

Delete Webhook

DELETE /v1/webhooks/:id

Webhook Payload

All webhook payloads have this structure:

{
"id": "evt_xyz789",
"type": "post.published",
"createdAt": "2024-01-15T10:00:00Z",
"data": {
// Event-specific data
}
}

post.published

{
"id": "evt_xyz789",
"type": "post.published",
"createdAt": "2024-01-15T10:00:00Z",
"data": {
"id": "post_abc123",
"channel": "ch_def456",
"content": "Hello from Flow!",
"platformPostId": "1234567890",
"publishedAt": "2024-01-15T10:00:05Z"
}
}

post.failed

{
"id": "evt_xyz789",
"type": "post.failed",
"createdAt": "2024-01-15T10:00:00Z",
"data": {
"id": "post_abc123",
"channel": "ch_def456",
"content": "Hello from Flow!",
"error": {
"code": "rate_limited",
"message": "Twitter rate limit exceeded"
}
}
}

Signature Verification

Webhooks include a signature header for verification:

X-Flow-Signature: sha256=abc123...

Verify the signature:

import crypto from 'crypto';
function verifySignature(payload: string, signature: string, secret: string): boolean {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}