StackSpendDocs

Webhooks

Receive real-time HTTP POST notifications when events occur in StackSpend — such as a new anomaly being detected or a budget threshold being crossed.

How webhooks work

When an event occurs in StackSpend, it sends an HTTP POST request to each registered endpoint with a JSON body describing the event. Your server must respond with a 2xx status code within 10 seconds to acknowledge delivery.

Failed deliveries (non-2xx or timeout) are retried up to 5 times with exponential back-off over 24 hours.

Supported events

Event typeDescriptionStatus
anomaly.createdA new spend anomaly has been detected for a connected provider.Available
budget.threshold_crossedA provider has crossed a configured budget alert threshold.Coming soon

Creating a webhook endpoint

1

Open the Webhooks tab

Go to Settings → API → Webhooks and click Add endpoint.

2

Enter your URL

Paste the HTTPS URL of your server endpoint. StackSpend will POST events to this URL.

3

Copy your signing secret

After saving, a signing secret is shown once. Copy it immediately and store it securely — it will not be displayed again. If you lose it, rotate the secret from the endpoint's settings.

Store the secret securely.Treat the signing secret like a password. Use it only server-side to verify request signatures. Never expose it in client-side code or logs.

Request format

Every webhook delivery is an HTTP POST with a JSON body and the following headers:

HeaderValue
X-StackSpend-EventThe event type, e.g. anomaly.created
X-StackSpend-Event-IdA unique UUID for this delivery. Use this to deduplicate retries.
X-StackSpend-TimestampUnix timestamp (seconds) of when the event was sent.
X-StackSpend-Signaturesha256=<hex> — HMAC-SHA256 signature for verifying authenticity.

Verifying signatures

Always verify the signature before processing a webhook. This confirms the request came from StackSpend and has not been tampered with.

  1. Read the raw request body as a string (do not parse it yet).
  2. Build the signed string: {timestamp}.{raw_body}, where timestamp is the value from X-StackSpend-Timestamp.
  3. Compute HMAC-SHA256 of that string using your signing secret as the key.
  4. Hex-encode the result and prepend sha256=.
  5. Compare to the X-StackSpend-Signature header using a constant-time comparison.
  6. Reject the request if the signatures do not match, or if the timestamp is more than 5 minutes old.
Replay attacks.The 5-minute timestamp check prevents replay attacks. Always validate the timestamp before trusting the payload.

Example payload — anomaly.created

{
  "event": "anomaly.created",
  "event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": 1234567890,
  "data": {
    "id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
    "provider_type": "aws",
    "service": "Amazon EC2",
    "severity": "high",
    "deviation_percent": 82.4,
    "actual_cost": 450.00,
    "expected_cost": 247.00,
    "detected_date": "2025-01-15"
  }
}

API management

Webhook endpoints can also be managed programmatically via the public API. All endpoints require a valid API key.

MethodEndpointDescription
GET/api/v1/public/webhooks/endpointsList all webhook endpoints.
POST/api/v1/public/webhooks/endpointsCreate a new webhook endpoint.
PATCH/api/v1/public/webhooks/endpoints/{id}Update an endpoint (URL, enabled state).
DELETE/api/v1/public/webhooks/endpoints/{id}Delete a webhook endpoint.
POST/api/v1/public/webhooks/endpoints/{id}/testSend a synthetic test event to the endpoint.
Test endpoint.The test endpoint sends a synthetic event to your URL so you can verify delivery and signature verification without waiting for a real anomaly to occur.
Webhooks — StackSpend Docs — StackSpend Docs