What are Webhooks?
Webhooks provide real-time HTTP callbacks when events occur in the Hyperion platform. Instead of polling the API for changes, you configure an endpoint that Hyperion calls whenever relevant activities happen.
Webhooks enable:
- Real-time notifications: Receive instant updates when events occur
- System integration: Connect Hyperion to your existing systems
- Automated workflows: Trigger actions based on platform activity
- Reduced polling: Eliminate the need to continuously check for changes
How are webhooks structured?
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"partnerId": "550e8400-e29b-41d4-a716-446655440001",
"url": "https://example.com/webhooks/hyperion",
"activityTypes": ["event:create", "monitorable:update"],
"enabled": true,
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
Webhook Fields
| Field | Description |
|---|---|
id | Unique identifier assigned by Hyperion |
partnerId | ID of the partner organization that owns the webhook |
url | Your HTTPS endpoint that receives webhook notifications |
activityTypes | Array of activity types this webhook subscribes to |
enabled | Flag to enable or disable the webhook |
createdAt | Timestamp when the webhook was created |
updatedAt | Timestamp when the webhook was last updated |
Activity Types
Subscribe to specific types of activities based on your integration needs:
Application
| Type | Description |
|---|---|
application:create | A new application has been created |
application:update | An existing application has been updated |
application:delete | An application has been deleted |
Event
| Type | Description |
|---|---|
event:create | A new event has been created for a monitorable |
event:update | An existing event has been updated |
Member
| Type | Description |
|---|---|
member:create | A new member has been added to the partner |
member:update | An existing member has been updated |
member:delete | A member has been removed from the partner |
Member Invitation
| Type | Description |
|---|---|
member-invitation:create | A new member invitation has been created |
member-invitation:accept | A member invitation has been accepted |
member-invitation:delete | A member invitation has been deleted |
Monitorable
| Type | Description |
|---|---|
monitorable:create | A new monitorable has been created |
monitorable:update | An existing monitorable has been updated |
Monitorable Incident
| Type | Description |
|---|---|
monitorable-incident:create | A monitorable incident has been opened |
monitorable-incident:action:create | An operator action has been added to a monitorable incident |
See Monitorable Incidents for action types and sample payloads.
Webhook
| Type | Description |
|---|---|
webhook:create | A new webhook has been created |
webhook:update | An existing webhook has been updated |
webhook:delete | A webhook has been deleted |
You can subscribe to multiple activity types with a single webhook, or create separate webhooks for different activity types.
Webhook Payload
When an activity matches your webhook's activity types, Hyperion sends a POST request to your URL with a JSON payload:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"partnerId": "550e8400-e29b-41d4-a716-446655440001",
"entityId": "550e8400-e29b-41d4-a716-446655440002",
"entityType": "EVENT",
"activityType": "event:create",
"scope": "event:read",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"partnerId": "550e8400-e29b-41d4-a716-446655440001",
"monitorableId": "550e8400-e29b-41d4-a716-446655440003",
"externalId": "ext-event-12345",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
},
"createdAt": "2024-01-15T10:30:00Z"
}
Payload Fields
| Field | Description |
|---|---|
id | Unique identifier for the activity |
partnerId | ID of the partner the activity belongs to |
entityId | ID of the entity that triggered the activity |
entityType | Type of entity (e.g., EVENT, MONITORABLE, WEBHOOK) |
activityType | The activity type that triggered this delivery |
scope | The scope required to view the activity |
data | Object snapshot of the entity at the time of the activity |
createdAt | Timestamp when the activity was created |
Signature Verification
Always verify webhook signatures to ensure notifications were sent from the Hyperion platform and haven't been tampered with.
Hyperion cryptographically signs every webhook delivery using a CA-backed certificate. By verifying these signatures you can confirm that the payload was genuinely sent by Hyperion and has not been tampered with.
Signature Headers
Each webhook request includes three HTTP headers following RFC 9421 (HTTP Message Signatures):
| Header | Description |
|---|---|
Signature-Input | Describes the covered components and parameters: signing key ID and creation timestamp |
Signature | Contains the base64-encoded signature value, wrapped in colons |
Signature-Agent | The fully qualified URL to the JWKS endpoint for retrieving the verification key |
Example headers on a webhook request:
Signature-Input: sig=("@content");created=1618884473;keyid="a1b2c3d4"
Signature: sig=:wNmSUAhwb5LxtOtOpNa6W5xj067m5hFrj0XQ4fvpaCLx0NKocgPquLgyahnzDnDAUy5eCdlYUEkLIj+32oiasw==:
Signature-Agent: https://api.example.com/.well-known/jwks.json
Signature-Input Parameters
| Parameter | Description |
|---|---|
@content | Indicates the signature covers the request body |
created | Unix timestamp of when the signature was generated |
keyid | The ID of the signing certificate used |
The label before the = (e.g., sig) is a unique identifier for the signature entry. This label must match between the Signature-Input and Signature headers. Always parse it dynamically rather than hardcoding a specific value. The signature value in the Signature header is wrapped in colons (:).
JWKS Endpoint
Hyperion exposes the webhook signing public certificate at the well-known JWKS endpoint:
GET /.well-known/jwks.json
The same signing key is also included in the partner JWKS (GET /partner/.well-known/jwks.json) alongside your encryption keys, so partners that already fetch that endpoint can verify webhook signatures without a second call.
The /.well-known/jwks.json endpoint does not require
authentication. The fully qualified URL is also provided in the
Signature-Agent header on every webhook delivery.
The JWKS response includes the signing public certificate:
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "S3P3fLgv9qxIdBtiT10D8XAM-AUBwIuX0iCZ1Ozgfos",
"y": "Lev6LSJG1a7VsLM5Yx01wHwFJj0DGHJuJUOXreS_tp8",
"kid": "a1b2c3d4",
"use": "sig",
"alg": "ES256",
"x5c": ["MIIByzCCAXI...base64-der-certificate..."]
}
]
}
| Field | Description |
|---|---|
kty | Key type (e.g., EC, RSA, OKP) |
crv | Curve name for EC/OKP keys (e.g., P-256, Ed25519) |
x | Base64URL-encoded X coordinate (EC/OKP keys) |
y | Base64URL-encoded Y coordinate (EC keys) |
kid | Key identifier matching the keyid in headers |
use | Key usage (always sig for signing) |
alg | Algorithm (e.g., ES256, RS256, EdDSA) |
x5c | X.509 certificate chain as base64-encoded DER certificates |
Verification Steps
- Parse the
keyidfrom theSignature-Inputheader - Extract the signature value from the
Signatureheader (the base64 string between the colons) - Fetch the JWKS from the URL in the
Signature-Agentheader (or from/.well-known/jwks.json) - Find the key matching the
keyid - Verify the signature against the raw request body using the key's algorithm
- Optionally, verify the
x5ccertificate chain against a trusted CA root
Verification Example
const crypto = require("crypto");
function parseSignatureInput(header) {
const labelMatch = header.match(/^([a-zA-Z][a-zA-Z0-9_-]*)=/);
const keyIdMatch = header.match(/keyid="([^"]+)"/);
const createdMatch = header.match(/created=(\d+)/);
if (!labelMatch || !keyIdMatch || !createdMatch) {
throw new Error("Invalid Signature-Input header format");
}
return {
label: labelMatch[1],
keyId: keyIdMatch[1],
created: parseInt(createdMatch[1], 10),
};
}
function parseSignature(header) {
const match = header.match(/^([a-zA-Z][a-zA-Z0-9_-]*)=:([^:]+):$/);
if (!match) throw new Error("Invalid Signature header format");
return { label: match[1], signature: match[2] };
}
const VERIFY_ALGORITHMS = {
EdDSA: null,
ES256: "sha256",
ES384: "sha384",
ES512: "sha512",
RS256: "sha256",
RS384: "sha384",
RS512: "sha512",
};
async function getSigningKey(jwksUrl, kid) {
const response = await fetch(jwksUrl);
const jwks = await response.json();
const key = jwks.keys.find((k) => k.kid === kid);
if (!key) throw new Error("Signing key not found");
return {
publicKey: crypto.createPublicKey({ key, format: "jwk" }),
algorithm: VERIFY_ALGORITHMS[key.alg] ?? null,
};
}
app.post("/webhooks/hyperion", async (req, res) => {
const input = parseSignatureInput(req.headers["signature-input"]);
const sig = parseSignature(req.headers["signature"]);
const jwksUrl = req.headers["signature-agent"];
if (input.label !== sig.label) {
return res.status(401).send("Signature label mismatch");
}
const { publicKey, algorithm } = await getSigningKey(jwksUrl, input.keyId);
const isValid = crypto.verify(
algorithm,
Buffer.from(req.rawBody),
publicKey,
Buffer.from(sig.signature, "base64"),
);
if (!isValid) {
return res.status(401).send("Invalid signature");
}
res.status(200).send("OK");
});
Cache JWKS responses to reduce latency. If a keyid is not found
in your cache, refresh the JWKS to pick up newly rotated keys.
Use Cases
Real-Time Alarm Notifications
Subscribe to event:create to receive immediate notifications when alarms are triggered:
{
"url": "https://your-monitoring-system.com/api/hyperion/events",
"activityTypes": ["event:create"],
"enabled": true
}
Your system can then:
- Alert on-duty operators
- Trigger automated response protocols
- Log events for compliance
Integration with Third-Party Systems
Connect Hyperion to your CRM, ticketing system, or analytics platform:
{
"url": "https://your-crm.com/webhooks/hyperion",
"activityTypes": [
"event:create",
"event:update",
"monitorable:create",
"monitorable:update"
],
"enabled": true
}
Audit Logging
Capture all platform activity for compliance and auditing:
{
"url": "https://your-audit-service.com/log",
"activityTypes": [
"application:create",
"application:update",
"application:delete",
"event:create",
"event:update",
"member:create",
"member:update",
"member:delete",
"member-invitation:create",
"member-invitation:accept",
"member-invitation:delete",
"monitorable:create",
"monitorable:update",
"webhook:create",
"webhook:update",
"webhook:delete"
],
"enabled": true
}
Automated Workflows
Trigger automated actions when specific events occur:
{
"url": "https://your-automation-platform.com/triggers/hyperion",
"activityTypes": ["event:create"],
"enabled": true
}
Use webhooks to:
- Send SMS alerts to emergency contacts
- Create tickets in your support system
- Update dashboards in real-time
- Trigger home automation actions
Best Practices
Endpoint Requirements
- Use HTTPS endpoints only
- Respond with a 2xx status code within 30 seconds
- Implement idempotency to handle duplicate deliveries
- Store the webhook payload before processing
Error Handling
- If your endpoint returns a non-2xx response, Hyperion will retry the delivery
- Implement proper logging to troubleshoot delivery issues
- Monitor your webhook endpoint for availability
Security
- Always verify the
SignatureandSignature-Inputheaders using the JWKS endpoint provided in theSignature-Agentheader - Cache JWKS responses to reduce latency, but refresh when a
keyidis not found - Use a unique, non-guessable URL for your webhook endpoint
- Validate the payload structure before processing
Related Resources
Guides
- Receive Notifications - Step-by-step guide to set up webhooks
API Reference
- Create Webhook - Register a new webhook
- Get Webhook - Retrieve webhook details
- List Webhooks - List all webhooks
- Update Webhook - Modify webhook configuration
- Delete Webhook - Remove a webhook
Related Concepts
- Events - Activities that trigger webhook notifications
- Monitorables - Entities that generate events