Skip to main content

Documentation Index

Fetch the complete documentation index at: https://knowledge.flowella.io/llms.txt

Use this file to discover all available pages before exploring further.

Outbound webhooks let your systems react to events in Flowella in near real-time, without polling the API. You configure a URL and a list of event types, and Flowella POSTs a signed JSON payload to that URL whenever one of those events fires.

Configuring a webhook

You need the Owner or Admin role.
1

Open Settings → Webhooks

In the Flowella app, go to Settings → Webhooks.
2

Add a webhook

Click Add webhook, paste the public HTTPS URL of your endpoint, and pick the event types you want to receive.
3

Save the signing secret

Flowella generates a unique signing secret for the webhook. Copy it — you will use it to verify incoming requests.
4

Send a test

Click Send test to dispatch a webhook.test payload immediately. Check your endpoint received it and responded with a 2xx.

Event types

You can subscribe to any of these product events:
EventWhen it fires
message.receivedAn inbound WhatsApp message has arrived from a contact
message.sentFlowella has accepted your outbound message and submitted it to Meta
message.deliveredMeta confirmed the message was delivered to the recipient’s device
message.readThe recipient opened the message
message.failedMeta returned a failure for the message
conversation.openedA conversation has moved into the open state
conversation.closedA conversation has been closed
optout.createdA contact opted out on a specific channel
template.status_updatedMeta changed a template’s status (approved, rejected, paused, disabled)
webhook.test is sent only when you click Send test — you do not subscribe to it explicitly.

Request format

Flowella POSTs a JSON body to your URL with these headers:
POST https://your-endpoint.example.com/flowella
Content-Type: application/json
User-Agent: Flowella-Webhooks/1
X-Flowella-Signature: <hex digest>
Payloads are capped at 256 KB. Larger objects are summarised — use the API to fetch the full record by ID if you need it. The body shape varies by event but always includes:
{
  "event": "message.delivered",
  "timestamp": "2025-01-15T14:30:00.000Z",
  "organizationId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
  "data": { "...event-specific fields..." }
}

Verifying signatures

Every request includes an X-Flowella-Signature header. The value is the HMAC-SHA256 hex digest of the raw UTF-8 request body keyed with your webhook’s signing secret. Verify before processing:
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(signatureHeader, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}
import hmac, hashlib

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header)
Always sign over the raw body bytes before any JSON parsing or middleware reformats the payload. If your framework reserialises JSON, the signature will not match.

Responses, retries, and timeouts

  • Timeout: Flowella waits up to 10 seconds for your endpoint to respond.
  • Success: any 2xx response is treated as successful delivery.
  • Retries: failed deliveries are retried up to 3 attempts with backoff.
  • Auto-disable: if a webhook accumulates 10 consecutive failures, Flowella deactivates it. You will need to re-enable it from Settings → Webhooks after fixing your endpoint.
Your endpoint should return as fast as possible — defer any heavy processing to a background queue on your side.

Idempotency

Webhooks may be retried, so the same logical event can arrive more than once. To process safely:
  • Use the data.id of the event (or a derived key like event + data.messageId) as an idempotency key.
  • Keep a short-lived cache of processed keys (a few hours is enough for retries).
  • Treat duplicates as no-ops.

Listing and managing deliveries

Settings → Webhooks shows recent delivery attempts per webhook, including:
  • Timestamp
  • Event type
  • Response status
  • A truncated response body (up to ~1 KB) for debugging
If a webhook is deactivated due to repeated failures, the same page lets you re-enable it.

Local development

The simplest way to develop against webhooks locally is to forward a public tunnel (for example, ngrok or Cloudflare Tunnel) to your dev server and point the webhook URL at the tunnel host. Use Send test to fire payloads on demand without waiting for real WhatsApp activity.
Need to react to events that aren’t on the list? Tell us at support — we add events as customers ask for them.