Webhooks

Webhooks notify your application in real-time when events occur in FLXBL. Build integrations, trigger workflows, and keep external systems in sync.

How Webhooks Work

When an entity is created, updated, or deleted, FLXBL sends an HTTP POST request to your configured endpoint with details about the event.

100% Drag to pan
flowchart LR
    subgraph flxbl [FLXBL]
        A[Entity Created] --> B[Webhook Queue]
        B --> C[HTTP POST]
    end
    
    subgraph yourApp [Your Application]
        C -->|Signed Payload| D[Webhook Endpoint]
        D --> E[Verify Signature]
        E --> F[Process Event]
    end
    
    F --> G[Send Email]
    F --> H[Update Cache]
    F --> I[Sync to CRM]
Webhook delivery flow

Event Types

FLXBL can send notifications for these entity lifecycle events:

100% Drag to pan
flowchart TB
    subgraph events [Webhook Events]
        direction LR
        Created[entity.created]
        Updated[entity.updated]
        Deleted[entity.deleted]
    end
    
    subgraph filters [Event Filters]
        direction LR
        AllEntities[All Entities]
        SpecificEntities["Specific Entities (Order, User)"]
    end
    
    events --> filters
Available webhook events and filters
Event Type Description When Triggered
entity.created A new entity record was created POST to /api/v1/dynamic/{Entity}
entity.updated An existing record was modified PUT or PATCH to /api/v1/dynamic/{Entity}/:id
entity.deleted A record was deleted DELETE to /api/v1/dynamic/{Entity}/:id

Creating Webhooks

Via REST API

// Create a webhook via REST API
POST /api/v1/webhooks
{
  "targetUrl": "https://your-app.com/webhooks/flxbl",
  "eventTypes": ["entity.created", "entity.updated"],
  "entityNames": ["Order", "Customer"],  // Optional filter
  "schemaName": "production"
}

// Response
{
  "id": "wh_abc123",
  "targetUrl": "https://your-app.com/webhooks/flxbl",
  "eventTypes": ["entity.created", "entity.updated"],
  "entityNames": ["Order", "Customer"],
  "signingSecret": "whsec_abc123def456...",  // Store securely!
  "isActive": true,
  "createdAt": "2025-01-15T10:30:00Z"
}
Important: Store the signingSecret securely. You'll need it to verify webhook signatures. It's only shown at creation time.

Via MCP (AI Assistant)

// Using the FLXBL MCP tool
// In Cursor/Windsurf, ask the AI:

"Create a webhook to notify my app when 
 Orders are created or updated"

// The AI will use manage_webhooks with:
{
  "action": "create",
  "targetUrl": "https://your-app.com/webhooks/orders",
  "eventTypes": ["entity.created", "entity.updated"],
  "entityNames": ["Order"],
  "schemaName": "production"
}

Webhook Payload

Each webhook delivery includes the event details and the full entity record:

// Webhook payload structure
{
  "id": "evt_xyz789",
  "type": "entity.created",
  "timestamp": "2025-01-15T10:30:00Z",
  "data": {
    "entityName": "Order",
    "entityId": "node_abc123",
    "record": {
      "id": "node_abc123",
      "customerId": "node_customer_456",
      "total": 299.99,
      "status": "pending",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  },
  "tenant": {
    "id": "tenant_xyz",
    "name": "Acme Corp"
  }
}

Signature Verification

FLXBL signs every webhook payload with your signing secret. Always verify signatures to ensure the request came from FLXBL.

The signature is sent in the X-Webhook-Signature header:

X-Webhook-Signature: sha256=abc123def456...

Node.js / TypeScript

// Verify webhook signature (Node.js example)
import crypto from 'crypto';

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  const providedSig = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(providedSig)
  );
}

// Express webhook handler
app.post('/webhooks/flxbl', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = req.body.toString();
  
  if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(payload);
  
  // Process the webhook
  switch (event.type) {
    case 'entity.created':
      handleEntityCreated(event.data);
      break;
    case 'entity.updated':
      handleEntityUpdated(event.data);
      break;
    case 'entity.deleted':
      handleEntityDeleted(event.data);
      break;
  }
  
  res.status(200).send('OK');
});

Python

# Verify webhook signature (Python example)
import hmac
import hashlib

def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    provided = signature.replace('sha256=', '')
    
    return hmac.compare_digest(expected, provided)

# Flask webhook handler
@app.route('/webhooks/flxbl', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Webhook-Signature')
    payload = request.get_data()
    
    if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
        return 'Invalid signature', 401
    
    event = request.get_json()
    
    if event['type'] == 'entity.created':
        handle_entity_created(event['data'])
    # ... handle other events
    
    return 'OK', 200

Managing Webhooks

List Webhooks

// List all webhooks
GET /api/v1/webhooks

// Response
{
  "webhooks": [
    {
      "id": "wh_abc123",
      "targetUrl": "https://your-app.com/webhooks/flxbl",
      "eventTypes": ["entity.created", "entity.updated"],
      "entityNames": ["Order", "Customer"],
      "isActive": true,
      "lastTriggered": "2025-01-16T14:22:00Z",
      "successRate": 0.98
    }
  ]
}

Update and Delete

// Update a webhook
PATCH /api/v1/webhooks/wh_abc123
{
  "isActive": false  // Temporarily disable
}

// Delete a webhook
DELETE /api/v1/webhooks/wh_abc123

Use Cases

Send Notifications

Trigger email, SMS, or push notifications when records are created:

  • Email customer when their order status changes
  • Notify team when a new support ticket is created
  • Send welcome email when user signs up

Sync External Systems

Keep data in sync across your stack:

  • Update search index when products change
  • Sync customer data to CRM
  • Push events to analytics platform

Trigger Workflows

Automate business processes:

  • Start fulfillment when order is placed
  • Generate invoice when subscription renews
  • Archive data when record is deleted

Best Practices

Security

  • Always verify signatures - Never trust unverified payloads
  • Use HTTPS - Webhook URLs must use TLS
  • Store secrets securely - Use environment variables or secret management

Reliability

  • Respond quickly - Return 2xx within 5 seconds
  • Process asynchronously - Queue heavy processing for later
  • Handle duplicates - Webhooks may be retried; make handlers idempotent

Filtering

  • Use entity filters - Only receive events for entities you care about
  • Subscribe to specific events - Don't process events you don't need

Retry Policy

If your endpoint returns a non-2xx status code or times out, FLXBL retries delivery with exponential backoff:

Attempt Delay
1st retry 1 minute
2nd retry 5 minutes
3rd retry 30 minutes
4th retry 2 hours
5th retry 8 hours

After 5 failed attempts, the webhook is marked as failed and no further retries occur.

Troubleshooting

"Webhook not receiving events"

  • Verify the webhook is active (isActive: true)
  • Check that your endpoint is publicly accessible
  • Ensure your firewall allows FLXBL's IP addresses
  • Check the webhook's event types and entity filters

"Signature verification failing"

  • Verify you're using the correct signing secret
  • Ensure you're hashing the raw request body (not parsed JSON)
  • Check for encoding issues - payload must be UTF-8

Next Steps