Webhooks
Webhooks API
Receive real-time notifications when events occur in Flow.
Webhook Events
| Event | Description |
|---|---|
post.scheduled | A post was scheduled |
post.published | A post was successfully published |
post.failed | A post failed to publish |
channel.created | A channel was created |
channel.deleted | A channel was deleted |
Create Webhook
POST /v1/webhooksRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS URL to receive webhook events |
events | string[] | Yes | Array of event types to subscribe to |
secret | string | No | Custom secret for signature verification |
Example Request
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/webhooksExample 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/:idWebhook 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) );}