Build
Webhooks
Have Flung tell your server when posts publish or fail and when accounts need a person, instead of asking again and again.
TL;DR
| Question | Answer |
|---|---|
| How do I start? | Register an https endpoint and keep the whsec_ secret it returns. |
| How do I know an event is from Flung? | Verify its signature. Flung signs to the Standard Webhooks spec, so the SDK or any Standard Webhooks library checks it. |
| What if my endpoint is down? | Flung tries again, for a while, with growing gaps. Each event keeps its id, so drop ids you have already handled. |
| Can I rotate the secret? | Yes. Flung signs with both secrets while you switch, and the SDK accepts either. |
Register an endpoint
bash
curl -X POST 'https://api.flung.dev/v1/webhook-endpoints' \ --header "Authorization: Bearer $FLUNG_API_KEY" \ --header 'Content-Type: application/json' \ --header "Idempotency-Key: $(uuidgen)" \ --data '{ "url": "https://example.com/webhooks/flung", "events": [ "post.published", "post.failed" ]}'ts
import { Flung } from '@flung.dev/sdk'
const flung = new Flung({ apiKey: process.env.FLUNG_API_KEY! })const result = await flung.webhookEndpoints.create({ url: 'https://example.com/webhooks/flung', events: [ 'post.published', 'post.failed', ],})js
const response = await fetch('https://api.flung.dev/v1/webhook-endpoints', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.FLUNG_API_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID(), }, body: JSON.stringify({ url: 'https://example.com/webhooks/flung', events: [ 'post.published', 'post.failed', ], }),})if (!response.ok) throw new Error((await response.json()).error.message)const result = await response.json()Verify each event
Read the raw body as text: parsing it and writing it out again changes the bytes and breaks the signature.
ts
export async function POST(request: Request): Promise<Response> { const body = await request.text() const event = await verifyWebhook({ body, headers: request.headers, secret: process.env.FLUNG_WEBHOOK_SECRET! }) if (event.type === 'post.failed') console.warn(`Post ${event.data.post.id} failed`) return new Response(null, { status: 204 })}Events
| Event |
|---|
post.published |
post.partially_published |
post.failed |
target.published |
target.failed |
account.connected |
account.disconnected |
account.token_refresh_failed |
account.reconnect_required_soon |
inbox.received |
Every event has an id, a type, a createdAt time and data with the post or the account it is about.