Webhooks

Receive real-time notifications when events occur in your PlanningForge organization or teams.

What are Webhooks?

Webhooks allow you to build integrations that subscribe to certain events on PlanningForge. When an event is triggered, we send an HTTP POST request to the webhook's configured URL.

Use webhooks to integrate PlanningForge with your own systems, trigger notifications, update project management tools, or build custom automations.

Getting Started

Prerequisites

Before You Begin

  • Organization or Team Owner permissions - You need admin access to configure webhooks
  • A webhook endpoint - A publicly accessible URL that can receive POST requests
  • HTTPS support - Your endpoint must support HTTPS (recommended)
  • Ability to verify signatures - Your endpoint should validate webhook signatures for security

Best Practices

  • • Always verify webhook signatures to ensure authenticity
  • • Respond quickly (within 5 seconds) to avoid timeouts
  • • Process webhooks asynchronously to prevent delays
  • • Return 2xx status code to acknowledge receipt
  • • Use HTTPS endpoints for secure communication

Creating Your First Webhook

Organization-Level Webhooks

  1. Navigate to Organization Settings from the main menu
  2. Click on the Webhooks tab
  3. Click Create Webhook button
  4. Enter your webhook URL (e.g., https://api.yourapp.com/webhooks)
  5. Select the events you want to subscribe to
  6. Optionally add a description for easy identification
  7. Click Create
  8. Important: Copy and save the webhook secret - it's only shown once!

Team-Level Webhooks

  1. Go to your Team Dashboard
  2. Click Manage Team Webhooks in the Webhook Integrations section
  3. Follow the same steps as organization webhooks above
  4. Team webhooks receive events specific to that team only

Save Your Secret!

The webhook secret is only displayed once when you create the webhook. Store it securely - you'll need it to verify webhook signatures. If you lose it, you'll need to create a new webhook.

Webhook Validation

Why Validation?

When you create a webhook, PlanningForge sends a validation challenge to verify you control the endpoint. Your webhook stays in pending status until it responds correctly to this challenge.

How It Works

1

PlanningForge Sends Challenge

We send a POST request to your endpoint with:

{
  "type": "validation",
  "challenge": "a1b2c3d4e5f6...",
  "webhook_id": "whk_abc123...",
  "timestamp": 1730000000
}
2

Your Endpoint Responds

Echo back the challenge value in JSON format with a 2xx status code:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "challenge": "a1b2c3d4e5f6..."
}

Webhook Activated

If the challenge matches, your webhook status changes from pending to active and starts receiving events.

Implementation Examples

PHP/Laravel

Route::post('/webhook', function (Request $request) {
    // Handle validation challenge
    if ($request->input('type') === 'validation') {
        return response()->json([
            'challenge' => $request->input('challenge')
        ]);
    }

    // Handle actual webhook events...
    // (verify signature, process event, etc.)
});

Node.js/Express

app.post('/webhook', (req, res) => {
    // Handle validation challenge
    if (req.body.type === 'validation') {
        return res.status(200).json({
            challenge: req.body.challenge
        });
    }

    // Handle actual webhook events...
});

Python/Flask

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_json()

    # Handle validation challenge
    if payload.get('type') == 'validation':
        return jsonify({'challenge': payload['challenge']}), 200

    # Handle actual webhook events...

Validation Tips

  • • Respond within 30 seconds (validation timeout)
  • • Return exactly the same challenge value you received
  • • Ensure your endpoint is publicly accessible
  • • Return a 2xx status code (200, 201, 204, etc.)
  • • The response must be valid JSON with a "challenge" field

Available Events

PlanningForge webhooks can be triggered by various events. Choose the events that are relevant to your integration.

Team Events

Available for both team-level and organization-level webhooks:

Planning Sessions

  • session.started - Session begins
  • session.completed - Session finishes
  • session.cancelled - Session cancelled

Stories

  • story.created - New story added
  • story.estimated - Final estimate set
  • story.updated - Story modified

Voting

  • vote.cast - Individual vote submitted
  • vote.revealed - Votes revealed
  • consensus.reached - Team consensus

Team Changes

  • team.member.added - User added
  • team.member.removed - User removed
  • team.updated - Team details changed

Retrospectives

  • retrospective.started - Retro begins
  • retrospective.completed - Retro ends

* Only available when retrospectives feature is enabled

Organization-Only Events

These events are only available for organization-level webhooks:

User Management

  • user.created - New user added
  • user.updated - User modified
  • user.deleted - User removed
  • user.role_changed - Role modified

Organization

  • organization.updated - Org settings changed
  • team.created - New team created
  • team.deleted - Team removed

Security & Verification

Always Verify Signatures!

To ensure webhooks are actually from PlanningForge and not malicious actors, always verify the signature included in every webhook delivery.

How Signatures Work

Every webhook includes a signature in the X-PlanningForge-Signature header. This signature is created using HMAC-SHA256 with your webhook secret.

Example Signature Header:

sha256=a3b5c8d9e1f2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4

Verification Examples

PHP

function verifyWebhookSignature($payload, $signature, $secret) {
    $expectedSignature = 'sha256=' . hash_hmac(
        'sha256',
        json_encode($payload),
        $secret
    );

    return hash_equals($expectedSignature, $signature);
}

// Usage
$payload = json_decode($request->getContent(), true);
$signature = $request->header('X-PlanningForge-Signature');
$secret = 'your-webhook-secret';

if (!verifyWebhookSignature($payload, $signature, $secret)) {
    abort(401, 'Invalid signature');
}

Node.js

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
    const expectedSignature = 'sha256=' + crypto
        .createHmac('sha256', secret)
        .update(JSON.stringify(payload))
        .digest('hex');

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

Python

import hmac
import hashlib
import json

def verify_webhook_signature(payload, signature, secret):
    expected_signature = 'sha256=' + hmac.new(
        secret.encode('utf-8'),
        json.dumps(payload).encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected_signature)

Payload Structure

Headers

Every webhook delivery includes these HTTP headers:

Header Description
X-PlanningForge-Signature HMAC-SHA256 signature for verification
X-PlanningForge-Event Event type (e.g., "session.completed")
X-PlanningForge-Delivery-ID Unique delivery identifier
User-Agent PlanningForge-Webhooks/1.0

Payload Example

session.completed Event

{
  "event": "session.completed",
  "webhookable_type": "Team",
  "webhookable_id": "team-uuid-here",
  "timestamp": "2025-10-25T22:00:00+00:00",
  "session": {
    "id": "session-uuid",
    "name": "Sprint 45 Planning",
    "status": "completed",
    "started_at": "2025-10-25T20:00:00+00:00",
    "completed_at": "2025-10-25T22:00:00+00:00",
    "stories_estimated": 15,
    "average_estimate": 5.2
  },
  "team": {
    "id": "team-uuid",
    "name": "Engineering Team Alpha"
  }
}

Reliability & Retries

PlanningForge implements robust retry mechanisms to ensure webhook deliveries are reliable even when endpoints experience temporary issues.

Automatic Retries with Exponential Backoff

If your endpoint fails to respond with a 2xx status code or times out, PlanningForge automatically retries the delivery with increasing delays between attempts:

1st Retry
After 60s
2nd Retry
After 120s
3rd Retry
After 240s
4th Retry
After 480s (8m)
5th Retry
After 960s (16m)

This exponential backoff strategy gives your endpoint time to recover from temporary issues while minimizing load during outages.

Timeout Settings

Event Delivery Timeout

Your endpoint has 5 seconds to respond to webhook events

Process webhooks asynchronously if you need more time

Validation Timeout

Your endpoint has 30 seconds to respond to validation challenges

Validation happens once when webhook is created

Auto-Deactivation

To protect both systems, webhooks are automatically deactivated after 5 consecutive delivery failures.

To reactivate: Fix the issues on your end, then click the Reactivate button in the webhook management interface.

Delivery History & Monitoring

Every webhook delivery is recorded with complete details:

  • Delivery status - Success, failed, or pending
  • HTTP status code returned by your endpoint
  • Response time in milliseconds
  • Error messages if delivery failed
  • Full payload for debugging

View delivery history by clicking Logs next to any webhook in the management interface.

Testing Webhooks

Using webhook.site

  1. Go to webhook.site - you'll get a unique URL
  2. Copy the unique URL provided
  3. Create a webhook in PlanningForge using that URL
  4. Click the Send Test button on your webhook
  5. View the request details on webhook.site

Testing from Webhook Manager

Once you've created a webhook, you can test it directly from the webhook management interface:

  1. Navigate to your webhooks in Organization Settings or Team Webhooks
  2. Find the webhook you want to test
  3. Click the Test button
  4. A test payload will be sent to your endpoint
  5. Check the delivery status in the webhook details

Troubleshooting

Webhook Status: Pending

Note: A webhook stays in "pending" status until it successfully responds to the validation challenge. See the Webhook Validation section for complete details.

Validation Checklist:

  • ✓ Endpoint is publicly accessible (not localhost or behind firewall)
  • ✓ Endpoint returns 2xx status code (200, 201, 204, etc.)
  • ✓ Response is valid JSON with "challenge" field
  • ✓ Challenge value matches exactly what was sent
  • ✓ Response sent within 30 seconds (validation timeout)
  • ✓ Check if type === 'validation' in your endpoint code

Debugging Steps:

  • Check your server logs for incoming POST requests
  • Test your endpoint with a tool like Postman or curl
  • Verify SSL/TLS certificate is valid (if using HTTPS)
  • Try creating a webhook to webhook.site first to see the validation payload

Webhook Status: Failed

Auto-deactivation: Webhooks are automatically deactivated after 5 consecutive delivery failures to protect both systems. See the Reliability & Retries section for details.

Common Causes:

  • Endpoint returning errors (4xx or 5xx status codes)
  • Response taking too long (timeout: 5 seconds for events, 30s for validation)
  • SSL/TLS certificate issues
  • Firewall blocking PlanningForge's requests
  • Endpoint is down or unreachable
  • Signature verification failing (returning 401/403)

Resolution Steps:

  1. Check your endpoint logs for error details
  2. Verify endpoint returns 2xx status code for test deliveries
  3. Ensure response time is under 5 seconds (process asynchronously if needed)
  4. Test signature verification logic is working correctly
  5. Verify SSL/TLS certificate is valid and not expired
  6. Once fixed, click the Reactivate button in webhook management

💡 Pro Tip: Exponential Backoff

PlanningForge retries failed deliveries up to 5 times with increasing delays (60s, 120s, 240s, 480s, 960s). This gives your endpoint time to recover from temporary issues before auto-deactivation occurs.

Not Receiving Webhooks

Checklist:

  • Webhook status is Active (not Pending or Failed)
  • You've subscribed to the relevant events
  • Events are actually being triggered in PlanningForge
  • Endpoint URL is correct and publicly accessible
  • No firewall rules blocking PlanningForge IPs
  • SSL certificate is valid (if using HTTPS)

Need to manage webhooks programmatically?

Our REST API provides full webhook management capabilities including creation, updates, and delivery history.

View API Documentation →

Related Documentation

Integrations

Explore other ways to integrate PlanningForge with your tools.

View Integrations →

Security

Learn about PlanningForge security features and best practices.

Read Security Guide →

Support

Get help with webhooks setup and troubleshooting.

Contact Support →

Organization Settings

Learn how to configure your organization settings.

View Settings Guide →