Skip to content

Webhooks

Receive real-time notifications when events occur in TaskFlow.

What are Webhooks?

Webhooks allow your application to receive HTTP callbacks when specific events happen, enabling real-time integrations.

Use Cases

  • Sync tasks with external project management tools 💡
  • Send notifications to Slack or Microsoft Teams
  • Update analytics dashboards in real-time 🔍
  • Trigger CI/CD pipelines when deployment tasks complete
  • Log events to external monitoring systems

Webhook Events

TaskFlow sends webhooks for these events: 🚨

Event Type Description Payload Includes
task.created New task created
task.updated Task modified Updated task + changed fields
task.deleted Task deleted
task.completed Task marked complete Full task object
task.assigned Task assigned to user
comment.created Comment added Comment + task reference
workflow.triggered Workflow executed

Setting Up Webhooks

Create a Webhook Endpoint

Your endpoint must: 🛠️

  • Accept POST requests
  • Respond with 200 OK within 5 seconds
  • Verify the webhook signature (recommended) 🚨

Example endpoint (Python/Flask):

from flask import Flask, request
import hmac
import hashlib

app = Flask(__name__)

@app.route('/webhooks/taskflow', methods=['POST'])
def handle_webhook():
    # Verify signature
    signature = request.headers.get('X-TaskFlow-Signature')
    if not verify_signature(request.data, signature):
        return 'Invalid signature', 401

    # Process webhook
    event = request.json
    event_type = event['type']

    if event_type == 'task.created':
        handle_task_created(event['data'])
    elif event_type == 'task.updated':
        handle_task_updated(event['data'])

    return 'OK', 200

def verify_signature(payload, signature):
    """Verify webhook signature."""
    secret = 'your_webhook_secret'
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

This example shows basic webhook handling with signature verification.

Register Your Webhook

POST /v2/webhooks

Request Body 🛠️

{
  "url": "https://yourapp.com/webhooks/taskflow",
  "events": ["task.created", "task.updated", "task.completed"],
  "secret": "your_generated_secret_key",
  "enabled": true
}

Response

{
  "id": "wh_abc123",
  "url": "https://yourapp.com/webhooks/taskflow",
  "events": ["task.created", "task.updated", "task.completed"],
  "enabled": true,
  "created_at": "2024-02-10T15:00:00Z",
  "last_triggered": null,
  "delivery_success_rate": 0.0
}

Example (Python SDK)

webhook = client.webhooks.create(
    url="https://yourapp.com/webhooks/taskflow",
    events=["task.created", "task.updated"],
    secret="your_secret_key"
)

Webhook Payload

All webhook payloads follow this structure:

{
  "id": "evt_xyz789",
  "type": "task.created",
  "timestamp": "2024-02-10T16:45:22Z",
  "data": {
    "id": "task_abc123",
    "title": "Deploy to production",
    "status": "open",
    "priority": "high",
    ...
  },
  "metadata": {
    "account_id": "acc_123",
    "triggered_by": "user_456"
  }
}

Headers 🛠️

TaskFlow includes these headers with webhook requests:

Content-Type: application/json
X-TaskFlow-Event: task.created
X-TaskFlow-Signature: sha256=abc123...
X-TaskFlow-Delivery-ID: del_xyz789
  • X-TaskFlow-Event - The event type
  • X-TaskFlow-Signature - HMAC signature for verification
  • X-TaskFlow-Delivery-ID - Unique delivery attempt ID (for deduplication) 💡

Signature Verification

Always verify webhook signatures to ensure requests are from TaskFlow: 🚨

Verification Steps

  1. Extract the signature from the X-TaskFlow-Signature header
  2. Compute HMAC-SHA256 of the raw request body using your secret
  3. Compare the computed signature with the received signature 🛠️

Example (Python)

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    """Verify TaskFlow webhook signature."""
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    # Prefix with 'sha256='
    expected = f"sha256={expected_signature}"

    # Use constant-time comparison
    return hmac.compare_digest(signature, expected)

Example (Node.js)

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const expected = `sha256=${hmac.digest('hex')}`;

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Delivery and Retries

Delivery Guarantees 🔍

  • Webhooks are delivered at least once
  • Delivery order is not guaranteed
  • Failed deliveries are retried automatically

Retry Policy 🛠️

If your endpoint returns a non-2xx status code or times out:

  1. First retry: after 5 seconds
  2. Second retry: after 30 seconds
  3. Third retry: after 5 minutes
  4. Fourth retry: after 1 hour
  5. Fifth retry: after 6 hours

After 5 failed attempts, the webhook is marked as failed and deliveries stop. 💡

Monitoring Webhooks

Check webhook delivery status:

GET /v2/webhooks/{webhook_id}/deliveries

Returns recent delivery attempts with status codes and response times.

Testing Webhooks

Send Test Event 🛠️

Trigger a test webhook delivery:

POST /v2/webhooks/{webhook_id}/test
{
  "event_type": "task.created"
}

Sends a sample webhook to your endpoint for testing.

Local Development 💡

For local testing, use a tool like ngrok to expose your local server:

ngrok http 3000

Then register the ngrok URL as your webhook endpoint.

Webhook Limits 🚨

  • Maximum 10 webhooks per account
  • Maximum 1000 deliveries per webhook per day 🔍
  • Endpoint must respond within 5 seconds
  • Request body size limited to 10MB

Best Practices

Handle Duplicate Events 🛠️

Webhooks may be delivered more than once. Use the X-TaskFlow-Delivery-ID header or the event id to deduplicate:

processed_events = set()

def handle_webhook(event):
    event_id = event['id']
    if event_id in processed_events:
        return  # Already processed

    processed_events.add(event_id)
    # Process event...

Respond Quickly

Process webhooks asynchronously. Respond with 200 OK immediately, then process the event in the background:

@app.route('/webhooks/taskflow', methods=['POST'])
def webhook():
    event = request.json

    # Queue for background processing
    task_queue.enqueue(process_event, event)

    return 'OK', 200

Monitor Failures

Set up monitoring to alert you when webhook deliveries fail consistently.

Use HTTPS

Always use HTTPS endpoints for webhooks to protect sensitive data. 🚨

Next Steps