Skip to main content

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​

FieldDescription
idUnique identifier assigned by Hyperion
partnerIdID of the partner organization that owns the webhook
urlYour HTTPS endpoint that receives webhook notifications
activityTypesArray of activity types this webhook subscribes to
enabledFlag to enable or disable the webhook
createdAtTimestamp when the webhook was created
updatedAtTimestamp when the webhook was last updated

Activity Types​

Subscribe to specific types of activities based on your integration needs:

Application​

TypeDescription
application:createA new application has been created
application:updateAn existing application has been updated
application:deleteAn application has been deleted

Event​

TypeDescription
event:createA new event has been created for a monitorable
event:updateAn existing event has been updated

Member​

TypeDescription
member:createA new member has been added to the partner
member:updateAn existing member has been updated
member:deleteA member has been removed from the partner

Member Invitation​

TypeDescription
member-invitation:createA new member invitation has been created
member-invitation:acceptA member invitation has been accepted
member-invitation:deleteA member invitation has been deleted

Monitorable​

TypeDescription
monitorable:createA new monitorable has been created
monitorable:updateAn existing monitorable has been updated

Monitorable Incident​

TypeDescription
monitorable-incident:createA monitorable incident has been opened
monitorable-incident:action:createAn operator action has been added to a monitorable incident

See Monitorable Incidents for action types and sample payloads.

Webhook​

TypeDescription
webhook:createA new webhook has been created
webhook:updateAn existing webhook has been updated
webhook:deleteA 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​

FieldDescription
idUnique identifier for the activity
partnerIdID of the partner the activity belongs to
entityIdID of the entity that triggered the activity
entityTypeType of entity (e.g., EVENT, MONITORABLE, WEBHOOK)
activityTypeThe activity type that triggered this delivery
scopeThe scope required to view the activity
dataObject snapshot of the entity at the time of the activity
createdAtTimestamp 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):

HeaderDescription
Signature-InputDescribes the covered components and parameters: signing key ID and creation timestamp
SignatureContains the base64-encoded signature value, wrapped in colons
Signature-AgentThe 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​

ParameterDescription
@contentIndicates the signature covers the request body
createdUnix timestamp of when the signature was generated
keyidThe 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..."]
}
]
}
FieldDescription
ktyKey type (e.g., EC, RSA, OKP)
crvCurve name for EC/OKP keys (e.g., P-256, Ed25519)
xBase64URL-encoded X coordinate (EC/OKP keys)
yBase64URL-encoded Y coordinate (EC keys)
kidKey identifier matching the keyid in headers
useKey usage (always sig for signing)
algAlgorithm (e.g., ES256, RS256, EdDSA)
x5cX.509 certificate chain as base64-encoded DER certificates

Verification Steps​

  1. Parse the keyid from the Signature-Input header
  2. Extract the signature value from the Signature header (the base64 string between the colons)
  3. Fetch the JWKS from the URL in the Signature-Agent header (or from /.well-known/jwks.json)
  4. Find the key matching the keyid
  5. Verify the signature against the raw request body using the key's algorithm
  6. Optionally, verify the x5c certificate 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 Signature and Signature-Input headers using the JWKS endpoint provided in the Signature-Agent header
  • Cache JWKS responses to reduce latency, but refresh when a keyid is not found
  • Use a unique, non-guessable URL for your webhook endpoint
  • Validate the payload structure before processing

Guides​

API Reference​

  • Events - Activities that trigger webhook notifications
  • Monitorables - Entities that generate events