Webhooks: visión general (borrador)
Borrador técnico en inglés del modelo previsto de webhooks. No es un servicio operativo.
Borrador técnico en inglés · no operativo
Los webhooks salientes todavía no entregan eventos. El cuerpo en inglés que sigue conserva una propuesta técnica: no es un contrato publicado ni una guía para activar una función disponible. No implementes una integración de producción contra estos ejemplos. La API pública actual ofrece suscriptores; consulta la hoja de ruta.
Webhooks let Fluyio push events to your server the moment something happens in your account — a subscriber is created, a campaign is sent, a WhatsApp message is delivered. Instead of polling the API every few seconds, you give us a URL and we deliver a signed HTTP POST whenever a matching event occurs.
If you have ever integrated Stripe or Twilio webhooks, the model is identical: register an endpoint, subscribe to a list of event types, verify the signature on each delivery, and respond with 2xx.
How it works
┌──────────────┐ event happens ┌──────────────┐ HTTPS POST ┌──────────────┐
│ Fluyio │ ──────────────────▶ │ Delivery │ ───────────────▶ │ Your server │
│ backend │ │ queue │ (signed JSON) │ /webhooks │
└──────────────┘ └──────────────┘ └──────────────┘
▲ │
│ retry on non-2xx │
└──────────────────────────────────┘- Something happens in Fluyio — a subscriber is added to a list, a campaign finishes sending, a flow step fails.
- Fluyio enqueues a delivery for every endpoint that is subscribed to that event type.
- We sign the payload with your endpoint secret and POST it to your URL.
- Your server returns
200 OK. If it doesn't, we retry with exponential backoff for up to ~37 hours.
Webhooks complement the API — they don't replace it. Use the API to fetch state on demand, and webhooks to react to changes as they happen.
Setup in 4 steps
Create an endpoint on your server
Expose an HTTPS URL that accepts POST requests with a JSON body. Keep the handler fast: respond 200 OK immediately and process the payload asynchronously.
// pages/api/webhooks/fluyio.ts (Next.js)
export default function handler(req, res) {
// verify and enqueue, then:
res.status(200).send('ok');
}Register the endpoint with Fluyio
Open Webhooks in the dashboard and click Add endpoint. Pick the events you care about — avoid subscribing to * unless you really need every event. There is no public API for managing endpoints yet; it is on the roadmap.
The dashboard shows the endpoint secret (it starts with whsec_) exactly once. Store it in your environment — you cannot retrieve it again, only rotate it.
Verify the signature on every delivery
Each request includes a Fluyio-Signature header. Compute an HMAC SHA-256 of ${timestamp}.${raw_body} with your endpoint secret and compare it with the v1 value in the header. See verifying signatures for the full algorithm.
Respond 200 OK within 10 seconds
Any non-2xx response (or a timeout over 10s) is treated as a failure and will be retried. Defer heavy work to a background queue — the webhook handler should only verify, persist, and acknowledge.
Payload structure
Every webhook body has the same envelope:
{
"id": "evt_whk_01H8YQK7Z6N6P3K4M9C1RG2X4T",
"type": "subscriber.created",
"created": 1715000000,
"api_version": "2026-05-15",
"data": {
"object": {
"id": "sub_01H8YQK7Z6N6P3K4M9C1RG2X4T",
"email": "[email protected]",
"first_name": "Ada",
"last_name": "Lovelace",
"created_at": "2026-05-15T12:00:00Z"
}
}
}| Field | Type | Description |
|---|---|---|
id | string | Unique event ID. Prefixed evt_whk_. Use it for idempotency. |
type | string | Event name in resource.action form. See the events catalog. |
created | integer | Unix timestamp (seconds) when the event was emitted by Fluyio. |
api_version | string | API version that shaped the data payload. |
data.object | object | The resource that changed, in its current state. |
data.object will follow the API version current when delivery ships (2026-05-15 today). Per-endpoint version pinning is not available yet.
Quick receivers
A minimal receiver in your language of choice. Each example skips signature verification for brevity — production code must verify every request.
import express from 'express';
const app = express();
app.post(
'/webhooks/fluyio',
express.raw({ type: 'application/json' }),
(req, res) => {
const event = JSON.parse(req.body.toString());
switch (event.type) {
case 'subscriber.created':
console.log('new subscriber', event.data.object.email);
break;
case 'campaign.message.bounced':
console.log('bounce', event.data.object);
break;
}
res.status(200).send('ok');
},
);
app.listen(3000);Local development
The internet can't POST to localhost. Use a tunneling tool while developing:
- ngrok —
ngrok http 3000gives you a public HTTPS URL you can paste into the dashboard. - Cloudflared — free alternative.
- webhook.site — inspect raw deliveries without writing any code.
Once delivery is active, point a temporary endpoint at the tunnel URL to inspect real payloads.