Skip to main content

Webhook integration

Use this guide when you want Guard investigation alerts delivered to a custom URL for routing to a destination Guard does not support directly.

What the webhook integration doesDirect link to What the webhook integration does

Guard sends an HTTP POST request to a URL you provide whenever an investigation is opened that meets your configured risk threshold. The request body is a JSON payload containing the investigation details.

Webhooks are the most flexible integration — you control the receiving endpoint and can transform, forward, or act on the payload however you need.

PrerequisitesDirect link to Prerequisites

  • A Guard account with at least one protected harness
  • A publicly reachable HTTPS endpoint capable of receiving POST requests
  • Ability to verify HMAC signatures on the receiving side (recommended)

Connect a webhookDirect link to Connect a webhook

Step 1 — Start the connectionDirect link to Step 1 — Start the connection

Open Guard integrations — Webhook and select Add webhook.

Step 2 — Enter your endpoint URLDirect link to Step 2 — Enter your endpoint URL

Provide the full HTTPS URL of your receiving endpoint. Guard sends POST requests to this URL. The URL must be publicly reachable and respond with a 2xx status code to confirm receipt.

Step 3 — Copy your signing secretDirect link to Step 3 — Copy your signing secret

Guard generates a signing secret for each webhook. Copy and store this secret securely — you will use it to verify that incoming requests are genuinely from Guard.

Step 4 — Configure alert thresholdsDirect link to Step 4 — Configure alert thresholds

Choose which risk levels trigger a webhook delivery. By default, only high-risk investigations are sent. Adjust this to include medium-risk or restrict to critical only.

Step 5 — Send a test alertDirect link to Step 5 — Send a test alert

Use Send test alert to confirm delivery. Guard sends a sample payload to your endpoint and reports whether the response was 2xx.

Payload formatDirect link to Payload format

Guard sends a JSON payload with the following structure:

{
"event": "investigation.opened",
"timestamp": "2026-06-24T12:00:00Z",
"investigation": {
"id": "inv_abc123",
"url": "https://hol.org/guard/investigations/inv_abc123",
"risk_level": "high",
"risk_score": 87,
"artifact": {
"name": "example-package",
"version": "1.2.3"
},
"policy": {
"rule": "changed-after-approval",
"description": "Artifact changed after it was approved"
},
"factors": [
"approval receipt exists for previous version",
"content hash differs from approved snapshot"
]
}
}

The event field identifies what happened. The investigation object contains all details needed to take action or forward the alert.

Signature verificationDirect link to Signature verification

Every webhook request includes an X-Guard-Signature header containing an HMAC-SHA256 signature of the request body, computed using your signing secret.

To verify a request:

  1. Read the raw request body
  2. Compute HMAC-SHA256 using your signing secret as the key
  3. Compare the result to the value in the X-Guard-Signature header
  4. Reject the request if the signatures do not match

Verification prevents forged requests from triggering actions on your endpoint. It is strongly recommended for any webhook handling real investigations.

Retry policyDirect link to Retry policy

Guard retries failed deliveries automatically:

AttemptTiming
InitialImmediately on investigation open
Retry 11 minute after failure
Retry 25 minutes after failure
Retry 330 minutes after failure
Retry 42 hours after failure

A delivery is considered failed when your endpoint returns a non-2xx status code, times out, or is unreachable. After all retries are exhausted, the delivery is marked as failed in the delivery status log.

Guard does not retry successful deliveries. If your endpoint returns 2xx, the payload is not sent again for that investigation.

Configuration optionsDirect link to Configuration options

OptionDescription
Endpoint URLThe HTTPS URL that receives POST requests
Signing secretUsed to verify request authenticity
Risk thresholdMinimum risk level that triggers delivery
Test alertSend a sample payload to verify connectivity
Delivery statusView recent delivery attempts, response codes, and retry state

TroubleshootingDirect link to Troubleshooting

TimeoutDirect link to Timeout

If your endpoint does not respond within 10 seconds, Guard treats the delivery as failed and retries per the schedule. Accept the request quickly and process the payload asynchronously. Guard also treats any non-2xx response as a failure — return 2xx promptly even if background processing is still running.

Signature mismatchDirect link to Signature mismatch

If your verification logic rejects valid Guard requests, confirm that:

  • you are using the correct signing secret for this webhook
  • you are computing HMAC-SHA256 over the raw request body (not a parsed or re-serialized version)
  • you are comparing the full hex digest, not a truncated value

Regenerate the signing secret from integration settings if the secret was compromised or lost. The new secret applies to the next delivery.

Payload format unexpectedDirect link to Payload format unexpected

Guard always sends the JSON structure shown above. If your endpoint receives a different format, another service may be in the path — confirm the endpoint URL points directly to your handler.

Endpoint unreachableDirect link to Endpoint unreachable

If your endpoint is behind a firewall, VPN, or internal network, Guard cannot reach it — the URL must be publicly accessible over HTTPS. Use a reverse proxy or API gateway if your handler is not directly exposed.

Duplicate deliveriesDirect link to Duplicate deliveries

Under rare network conditions Guard may deliver the same payload more than once. Design your endpoint to be idempotent — use the investigation.id field to deduplicate so processing the same ID twice causes no side effects.

See it in productDirect link to See it in product

Next guidesDirect link to Next guides