Databee
PricingAPI Docs
  1. Home
  2. Blog
  3. Tutorials
TutorialsNov 5, 202516 min readUpdated Nov 12, 2025

Real-Time Grid Alerts: Building Webhook Integrations That Win

How to set up instant notifications when capacity becomes available in your target regions.

Alex Rivera avatar

Alex Rivera

Developer Advocate

Share:
Real-Time Grid Alerts: Building Webhook Integrations That Win - Tutorials article featured image showing Webhooks, Integration, Alerts

One of the most powerful features of the Databee platform is real-time alerting. Grid capacity is competitive—when an opportunity emerges, the first mover often wins. Webhooks let you know the moment conditions change, so you can act faster than competitors still waiting for weekly reports.

This guide covers everything you need to build robust webhook integrations: from basic setup to advanced patterns for production systems.

Why Real-Time Matters

Grid capacity changes constantly. Projects withdraw from interconnection queues. Studies complete with unexpected results. New generation comes online. Loads increase or decrease.

Any of these changes can create opportunities. A 100 MW project that withdraws from queue suddenly frees capacity that wasn't available yesterday. A transmission upgrade that completes opens new possibilities in a previously constrained area.

With traditional research methods, you might not learn about these changes for weeks or months. By then, competitors have already moved.

Webhooks change the equation. The moment we detect a material change in your target regions, we notify you. You can evaluate the opportunity and act while others are still unaware.

Basic Setup

### Registering a Webhook

First, register your webhook endpoint with Databee:

curl -X POST https://api.databee.io/v1/webhooks \

-H "Content-Type: application/json" \

-H "X-Payment-Proof: 0x..." \

-d '{

"url": "https://your-server.com/webhooks/databee",

"events": ["capacity.available", "queue.withdrawn"],

"filters": {

"regions": ["PJM", "ERCOT"],

"min_capacity_mw": 20,

"states": ["VA", "TX"]

},

"secret": "your-webhook-secret"

}'

### Configuration Options

url (required): Your HTTPS endpoint that will receive webhook payloads. Must be publicly accessible and respond within 5 seconds.

events (required): Array of event types to subscribe to. See Event Types below.

filters (optional): Narrow which events trigger notifications. Only events matching all specified filters will be sent.

secret (required): A secret string used to sign webhook payloads. Store this securely; you'll need it to verify authenticity.

### Event Types

### Filter Options

Receiving Webhooks

When an event matches your subscription, we send a POST request to your endpoint:

### Payload Structure

{

"webhook_id": "wh_abc123",

"event": "queue.withdrawn",

"timestamp": "2025-12-01T14:30:00Z",

"data": {

"queue_entry": {

"queue_id": "AC2-456",

"project_name": "Solar Project Alpha",

"capacity_mw": 75,

"substation": "Example 230kV",

"location": {

"state": "VA",

"county": "Loudoun"

}

},

"impact": {

"capacity_freed_mw": 75,

"queue_positions_shifted": 12,

"substations_affected": ["PJM-SUB-12345"]

}

},

"signature": "sha256=abc123..."

}

### Verifying Signatures

Always verify webhook signatures before processing. We sign payloads with HMAC-SHA256 using your webhook secret:

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)

);

}

// In your webhook handler

app.post('/webhooks/databee', (req, res) => {

const signature = req.headers['x-databee-signature'];

if (!verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET)) {

return res.status(401).send('Invalid signature');

}

// Process the webhook

handleWebhook(req.body);

// Respond quickly

res.status(200).send('OK');

});

### Response Requirements

Your endpoint must:

1. Respond within 5 seconds with a 2xx status code

2. Process asynchronously — don't do slow work in the request handler

3. Handle duplicates — we may retry failed deliveries

If your endpoint fails to respond correctly, we'll retry with exponential backoff: 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours.

Advanced Patterns

### Idempotency

Webhooks can be delivered multiple times due to network issues or retries. Your handler should be idempotent:

async function handleWebhook(payload) {

const webhookId = payload.webhook_id;

// Check if we've already processed this webhook

const exists = await db.webhooks.findOne({ webhookId });

if (exists) {

console.log('Duplicate webhook, skipping:', webhookId);

return;

}

// Process the webhook

await processCapacityChange(payload);

// Record that we've processed it

await db.webhooks.insert({

webhookId,

processedAt: new Date(),

payload

});

}

### Async Processing

Webhook handlers should respond immediately and process asynchronously:

app.post('/webhooks/databee', async (req, res) => {

// Verify signature (fast)

if (!verifySignature(req)) {

return res.status(401).send('Invalid');

}

// Queue for async processing (fast)

await queue.add('process-webhook', req.body);

// Respond immediately

res.status(200).send('OK');

});

// Process in background worker

queue.process('process-webhook', async (job) => {

const payload = job.data;

// Now we can take our time

await notifyTeam(payload);

await updateDatabase(payload);

await triggerAutomation(payload);

});

### Alerting Integration

Many teams want webhooks to trigger alerts in existing systems:

async function processCapacityChange(payload) {

if (payload.event === 'queue.withdrawn') {

const { capacity_freed_mw, substations_affected } = payload.data.impact;

// Significant capacity freed - alert the team

if (capacity_freed_mw >= 50) {

await slack.send({

channel: '#grid-intel',

text: `🔔 Major queue withdrawal detected!

*${capacity_freed_mw} MW* freed at ${substations_affected.length} substation(s)

Region: ${payload.data.queue_entry.location.state}

View details: https://databee.io/queue/${payload.data.queue_entry.queue_id}`

});

}

// Update our internal tracking

await updateCapacityTracking(payload);

}

}

### Automated Actions

For sophisticated users, webhooks can trigger automated actions:

async function processCapacityChange(payload) {

if (payload.event === 'capacity.available') {

const substation = payload.data.substation;

// Check if this substation is in our target list

const isTarget = await isTargetSubstation(substation.id);

if (isTarget && substation.available_mw >= 50) {

// Automatically query full details

const queueData = await databee.queryQueueIntel({

region: substation.region,

state: substation.location.state,

county: substation.location.county

});

// Generate report for site selection team

await generateSiteReport({

substation,

queueData,

triggeredBy: payload.webhook_id

});

// Notify team with actionable information

await notifyTeam({

type: 'opportunity',

urgency: 'high',

substation,

queueData,

action: 'Evaluate for interconnection application'

});

}

}

}

Monitoring and Debugging

### Webhook Dashboard

The Databee dashboard shows webhook delivery history:

  • All delivery attempts with timestamps
  • Response status codes
  • Payload contents
  • Retry history for failed deliveries

### Testing Webhooks

Use our test endpoint to send sample payloads:

curl -X POST https://api.databee.io/v1/webhooks/{webhook_id}/test \

-H "X-Payment-Proof: 0x..." \

-d '{

"event": "capacity.available"

}'

This sends a realistic test payload to your endpoint, helping you verify your integration before real events occur.

### Common Issues

Timeout errors: Your endpoint is taking too long. Move processing to a background queue.

Signature validation failures: Ensure you're using the exact payload bytes (not re-serialized JSON) and the correct secret.

Missing events: Check your filters. An event might not match your specified criteria.

Duplicate processing: Implement idempotency as described above.

Pricing

Webhook subscriptions are priced based on the number of events delivered:

Each webhook delivery counts as one event, regardless of retries.

Next Steps

Webhooks are the foundation for building responsive grid intelligence systems. Combined with our query APIs, you can build:

  • Real-time dashboards showing capacity changes as they happen
  • Automated alerting to notify teams of opportunities
  • AI agents that autonomously monitor and act on grid changes
  • Portfolio monitoring systems tracking multiple sites simultaneously

The grid is dynamic. With webhooks, your systems can be too.

WebhooksIntegrationAlertsReal-TimeDeveloperAPI
Alex Rivera avatar
Alex Rivera

Developer Advocate

Alex helps developers integrate with Databee. Previously built data platforms at Palantir.

View all posts by Alex
Back to all articles

Related Articles

Getting Started with the Grid Capacity API: A Developer's Guide

Nov 22, 2025

Getting Started with the Grid Capacity API: A Developer's Guide

The AI Power Crisis: Why Big Tech Is Desperately Hunting for Electricity

Dec 5, 2025

The AI Power Crisis: Why Big Tech Is Desperately Hunting for Electricity

PJM Interconnection Queue Decoded: What 2,400 Pending Projects Tell Us About Grid Capacity

Dec 2, 2025

PJM Interconnection Queue Decoded: What 2,400 Pending Projects Tell Us About Grid Capacity

Databee

The Power Intelligence Layer for AI Infrastructure.

Product

  • Regions
  • Pricing
  • API Reference
  • Dashboard

Company

  • About
  • Blog
  • Careers
  • Contact

Legal

  • Privacy
  • Terms
  • Security

© 2025 Databee. All rights reserved.

TwitterGitHubDiscord