Overview
Webhooks allow you to receive real-time HTTP POST notifications when events occur in your Brokkr organization. Instead of polling the API for changes, webhooks push data to your endpoint as events happen.
Available Events
Currently, webhooks support the following events:
DEVICE_LISTING_CREATED
- When a new device is added to our inventoryDEVICE_LISTING_UPDATED
- When device information or pricing is updated in our inventoryDEVICE_LISTING_DEPRECATED
- When a device is removed from our inventoryDEPLOYMENT_INTERRUPTED
- When a deployment is interrupted
Webhook Payload
All webhook events are delivered as HTTP POST requests with a JSON payload. The payload structure includes:
{ // Event-specific data data:{ "id": "device-uuid", "name": "NVIDIA RTX 4090", "status": "on demand", // ... additional fields } // Event type eventType: "DEVICE_LISTING_CREATED", // Timestamp timestamp: "2021-01-01T00:00:00.000Z", },
HTTP Headers
Each webhook request includes the following headers:
X-Webhook-Signature
- HMAC-SHA256 signature for request verificationX-Webhook-Event
- The event type (e.g., DEVICE_LISTING_CREATED)X-Webhook-Delivery
- Unique ID for this delivery attemptX-Webhook-Timestamp
- ISO 8601 timestamp of when the webhook was sentUser-Agent
- Always set to "Brokkr-Webhooks/1.0"
Signature Verification
To ensure webhook requests are coming from Brokkr, you should verify the signature included in theX-Webhook-Signature
header.
Verification Steps
- Extract the signature from the
X-Webhook-Signature
header - Compute an HMAC-SHA256 hash of the raw request body using your webhook secret
- Compare your computed signature with the received signature
Example Implementation
Node.js / JavaScript
const crypto = require('crypto'); function verifyWebhookSignature(body, signature, secret) { const expectedSignature = 'sha256=' + crypto.createHmac('sha256', secret) .update(body, 'utf8') .digest('hex'); // Use timingSafeEqual to prevent timing attacks return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) ); } // Express.js example app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-webhook-signature']; const isValid = verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET); if (!isValid) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(req.body); // Process the webhook event console.log('Received event:', event.eventType); res.status(200).send('OK'); });
Python
import hmac import hashlib def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool: expected_signature = 'sha256=' + hmac.new( secret.encode('utf-8'), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(signature, expected_signature) # Flask example from flask import Flask, request, abort app = Flask(__name__) @app.route('/webhook', methods=['POST']) def handle_webhook(): signature = request.headers.get('X-Webhook-Signature') body = request.get_data() if not verify_webhook_signature(body, signature, os.environ['WEBHOOK_SECRET']): abort(401) event = request.get_json() print(f"Received event: {event['eventType']}") return 'OK', 200
Go
package main import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "fmt" "io" "net/http" ) func verifyWebhookSignature(body []byte, signature, secret string) bool { h := hmac.New(sha256.New, []byte(secret)) h.Write(body) expectedSignature := "sha256=" + hex.EncodeToString(h.Sum(nil)) return hmac.Equal([]byte(signature), []byte(expectedSignature)) } func webhookHandler(w http.ResponseWriter, r *http.Request) { signature := r.Header.Get("X-Webhook-Signature") body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Failed to read body", http.StatusBadRequest) return } if !verifyWebhookSignature(body, signature, os.Getenv("WEBHOOK_SECRET")) { http.Error(w, "Invalid signature", http.StatusUnauthorized) return } // Process the webhook fmt.Println("Webhook verified and received") w.WriteHeader(http.StatusOK) }
Retry Logic
Brokkr implements automatic retry logic for failed webhook deliveries:
- Webhooks are retried up to 5 times with linear backoff
- Retry delays: 1, 2, 3, 4, and 5 minutes after each failure
- A webhook is considered successful if it returns a 2xx HTTP status code
- After 10 consecutive failures across multiple events, the webhook will be automatically disabled
Best Practices
- Always verify signatures - This ensures requests are authentic and haven't been tampered with
- Respond quickly - Return a 2xx response as soon as possible (within 10 seconds)
- Process asynchronously - Queue events for processing rather than handling them synchronously
- Handle duplicates - Use the delivery ID to ensure idempotent processing
- Store the raw payload - Keep the original event data for debugging and reprocessing
- Monitor failures - Set up alerts for webhook failures in your system
Testing Webhooks
To test your webhook implementation:
- Use a tool like webhook.site to create a temporary endpoint
- Create a webhook pointing to your test endpoint
- Trigger events in your Brokkr account (e.g., update device pricing)
- Verify the payload structure and test your signature verification
Webhook Management
You can manage webhooks through the Brokkr dashboard or API:
- Create webhooks with specific event subscriptions
- View delivery history and debug failed deliveries
- Manually retry successful or failed deliveries
- Update endpoint URLs and event subscriptions
- Regenerate webhook secrets if compromised
- Temporarily disable webhooks during maintenance
Security Considerations
- Always use HTTPS endpoints to prevent man-in-the-middle attacks
- Store webhook secrets securely (use environment variables, not hardcoded values)
- Implement rate limiting on your webhook endpoint
- Log webhook requests for audit purposes
- Rotate webhook secrets periodically
- Validate the webhook payload structure and data types