Webhook Management Portal
A web-based portal for managing webhook endpoints, subscribing to event notifications, rotating signing secrets, and monitoring delivery health.
Environments
| Environment | Webhook Portal URL | Partner Portal URL |
|---|---|---|
| Sandbox | https://webhook-portal-sandbox.k2cyber.co | https://partners-sandbox.k2cyber.co |
| Production | https://webhook-portal.k2cyber.co | https://partners.k2cyber.co |
Sandbox First
Start your webhook integration in the sandbox environment. Test your endpoint signature verification and event handling before moving to production.
Overview
The Webhook Management Portal provides a user-friendly interface for:
- Creating and managing HTTPS webhook endpoints (each with its own signing secret)
- Subscribing to specific event types
- Viewing delivery logs and monitoring endpoint health
- Rotating endpoint signing secrets for security
Getting Started
Access Methods
There are two ways to access the Webhook Portal:
Option 1: Partner Admin Login (Recommended)
If you're already a registered Partner Portal user:
- Navigate to the Webhook Portal URL
- Click Sign In
- Enter your Partner Portal email and password
- Your account is automatically provisioned for webhook access
This is the recommended approach for partner administrators who already have Partner Portal credentials.
Option 2: Register with a Webhook Key
For team members who need webhook access but don't have Partner Portal accounts:
- Obtain a Webhook Key from your partner administrator (created in the Partner Portal)
- Navigate to the Webhook Portal URL
- Click Need an account? Register
- Enter your email, password, and the webhook key
- Complete registration
The webhook key associates your account with your organization's partner account.
Webhook Keys vs Signing Secrets
The Webhook Key from the Partner Portal is only used for registration. The signing secrets used to verify webhook deliveries are generated separately when you create an endpoint in this portal.
Managing Endpoints
Create an Endpoint
- Navigate to Endpoints in the dashboard
- Click Add Endpoint
- Enter your webhook URL (must be HTTPS)
- Optionally add a description for reference
- Click Create Endpoint
Signing Secret - One-Time Display
When you create an endpoint, a signing secret is generated and displayed once. This is the secret you'll use to verify webhook signatures in your application. Copy and store it securely immediately—it cannot be retrieved later.
After creating an endpoint, you'll be prompted to subscribe to events immediately, or you can skip and add subscriptions later.
Endpoint Requirements
- Must use HTTPS (no HTTP or self-signed certificates in production)
- Must be publicly accessible
- Should respond with HTTP 2xx status codes within 8 seconds
- Must validate webhook signatures (see Signature Verification below)
Subscribe to Events
After creating an endpoint, subscribe to the events you want to receive:
- Click Add Events or Manage Subscriptions from the endpoint actions menu
- Select from available event types
- Click Subscribe
Available Event Types
Beta Event Types
Only three event types are currently available. More event types will be added soon, and event names and payloads are subject to change during the beta period.
| Event Type | Description |
|---|---|
quote.created | Triggered when a new quote is created |
policy.created | Triggered when a new policy is created |
broker.added | Triggered when a new broker is added to the system |
You can subscribe to multiple events on a single endpoint.
Event Topics Catalog
The Webhook Portal dashboard features an Event Topics Catalog that displays:
- All available event types grouped by category
- Detailed descriptions for each event
- Example payloads you can copy for testing
Use this catalog to understand the structure of webhook payloads before implementing your receiver.
Webhook Delivery Format
HTTP Headers
Each webhook delivery includes these headers:
| Header | Description |
|---|---|
Content-Type | Always application/json |
Event-ID | Unique event identifier for idempotency |
Timestamp | ISO 8601 timestamp of the delivery attempt |
X-Platform-Signature | HMAC-SHA256 signature for verification |
Sample Payloads
quote.created
{
"type": "quote.created",
"timestamp": "2025-10-21T15:02:31Z",
"brokerageId": "your-brokerage-id",
"data": {
"quoteId": "QTE-10293",
"partnerId": "your-partner-id",
"customer": {
"name": "Jane Doe",
"email": "jane.doe@email.com"
},
"product": "Cyber Insurance",
"requestedDate": "2025-10-21",
"status": "quoted"
}
}policy.created
{
"type": "policy.created",
"timestamp": "2025-10-21T15:02:31Z",
"brokerageId": "your-brokerage-id",
"data": {
"policyId": "POL-10293",
"partnerId": "your-partner-id",
"customer": {
"name": "Jane Doe",
"email": "jane.doe@email.com"
},
"product": "Cyber Insurance",
"effectiveDate": "2025-11-01",
"status": "active"
}
}broker.added
{
"type": "broker.added",
"timestamp": "2025-10-21T15:02:31Z",
"brokerageId": "your-brokerage-id",
"data": {
"brokerId": "BRK-78945",
"brokerageName": "Acme Insurance Brokers",
"contact": {
"name": "John Smith",
"email": "john.smith@acme-insurance.example"
},
"licensedStates": ["CA", "NY", "TX"],
"addedDate": "2025-10-21"
}
}Signature Verification
Verify the X-Platform-Signature header to ensure webhooks are genuinely from K2. Use the signing secret that was generated when you created the endpoint.
Signature Format
The signature is computed as:
HMAC-SHA256(secret, "${Event-ID}.${Timestamp}.${RequestBody}")The signature input is the concatenation of:
- The
Event-IDheader value - A period (
.) - The
Timestampheader value - A period (
.) - The raw request body (JSON string)
Verification Example (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(req, secret) {
const eventId = req.headers['event-id'];
const timestamp = req.headers['timestamp'];
const signature = req.headers['x-platform-signature'];
const body = JSON.stringify(req.body);
// Reconstruct the signed payload
const signedPayload = `${eventId}.${timestamp}.${body}`;
// Compute expected signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Use timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Express.js example
const ENDPOINT_SIGNING_SECRET = process.env.WEBHOOK_SIGNING_SECRET;
app.post('/webhooks', express.json(), (req, res) => {
if (!verifyWebhookSignature(req, ENDPOINT_SIGNING_SECRET)) {
console.error('Invalid webhook signature');
return res.status(401).send('Invalid signature');
}
// Signature valid - process the webhook
const eventId = req.headers['event-id'];
const eventType = req.body.type;
console.log(`Received ${eventType} event: ${eventId}`);
// Acknowledge receipt immediately
res.status(200).send('OK');
// Process asynchronously if needed...
});Verification Example (Python)
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
ENDPOINT_SIGNING_SECRET = os.environ.get('WEBHOOK_SIGNING_SECRET')
def verify_webhook_signature(request):
event_id = request.headers.get('Event-ID')
timestamp = request.headers.get('Timestamp')
signature = request.headers.get('X-Platform-Signature')
body = request.get_data(as_text=True)
# Reconstruct the signed payload
signed_payload = f"{event_id}.{timestamp}.{body}"
# Compute expected signature
expected_signature = hmac.new(
ENDPOINT_SIGNING_SECRET.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
# Use timing-safe comparison
return hmac.compare_digest(signature, expected_signature)
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
if not verify_webhook_signature(request):
return jsonify({'error': 'Invalid signature'}), 401
# Process the webhook
event_type = request.json.get('type')
event_id = request.headers.get('Event-ID')
print(f"Received {event_type} event: {event_id}")
return jsonify({'status': 'ok'}), 200Delivery & Retry Logic
Timeout
K2 expects a 2xx HTTP response within 8 seconds. If your endpoint takes longer to respond, the delivery will be marked as failed and retried.
Retry Behavior
Failed deliveries are retried with exponential backoff:
| Attempt | Delay Before Retry |
|---|---|
| 1 | Immediate |
| 2 | 1 second |
| 3 | 2 seconds |
| 4 | 4 seconds |
| 5 | 8 seconds |
| 6 | 16 seconds |
| 7 | 32 seconds |
| 8+ | 60 seconds (max) |
- Maximum of 10 delivery attempts per event
- After 10 failed attempts, the delivery is marked as permanently failed
Circuit Breaker
To protect both your endpoint and our system, K2 implements a circuit breaker:
- If an endpoint fails 5 times within 5 minutes, it is automatically disabled
- Disabled endpoints stop receiving webhook deliveries
- You can re-enable endpoints from the Webhook Portal after resolving the issue
Endpoint Disabled
If your endpoint is consistently failing, check the delivery logs for error details. Common issues include:
- Endpoint not responding within 8 seconds
- Endpoint returning non-2xx status codes
- Network connectivity issues
- Invalid SSL certificates
Monitoring Delivery Logs
The Logs page shows:
- Recent delivery attempts for all endpoints
- Success/failure status
- HTTP response codes and response times
- Retry attempt counts
- Event payloads for debugging
Use the Event-ID header value to track specific deliveries and implement idempotency in your system.
Rotating Endpoint Signing Secrets
To rotate an endpoint's signing secret:
- Navigate to the endpoint in your Endpoints list
- Click the actions menu (⋮) and select Rotate Secret
- Click Rotate Secret to confirm
- Copy the new signing secret immediately
- Update your application's signature verification with the new secret
Grace Period
When you rotate a secret, both the old and new secrets are valid for a short grace period. Update your application to accept the new secret during this period, then remove the old secret configuration.
Managing Subscriptions
From the endpoint details or actions menu:
- Add Events: Subscribe to new event types
- Manage Subscriptions: View and manage current subscriptions
- Remove Subscription: Unsubscribe from an event type by clicking the delete icon
Deleting Endpoints
To remove an endpoint:
- Navigate to the Endpoints page
- Click the actions menu (⋮) for the endpoint
- Select Delete Endpoint
Permanent Deletion
Deleting an endpoint removes all subscriptions and delivery history. This action cannot be undone.
Best Practices
Security
- Store signing secrets securely (use environment variables or secrets management)
- Always verify webhook signatures before processing
- Never commit secrets to version control
- Rotate secrets quarterly or after team changes
Reliability
- Implement idempotency using the
Event-IDheader to handle duplicate deliveries - Respond with 2xx immediately (within 8 seconds), then process asynchronously
- Log all webhook deliveries for debugging and auditing
- Use a queue or background job processor for time-consuming operations
Handling Failures
- Monitor for circuit breaker events (endpoint disabled notifications)
- Set up alerts for repeated delivery failures
- Check delivery logs regularly for error patterns
- Test endpoints after deploying changes
Idempotency
Webhooks may be delivered more than once due to retries. Use the Event-ID header to ensure you only process each event once:
const processedEvents = new Set(); // Use Redis/database in production
app.post('/webhooks', (req, res) => {
const eventId = req.headers['event-id'];
// Check if already processed
if (processedEvents.has(eventId)) {
console.log(`Event ${eventId} already processed, skipping`);
return res.status(200).send('OK');
}
// Mark as processed
processedEvents.add(eventId);
// Process the event...
res.status(200).send('OK');
});Support
If you encounter issues with webhook delivery:
- Check the Logs page for error details
- Verify your endpoint is accessible and responding within 8 seconds
- Confirm you're validating signatures correctly (including Event-ID and Timestamp in the signature)
- Check if your endpoint was disabled by the circuit breaker
- Contact support at ray@k2cyber.ai with the Event-ID