dexcost
Webhooks

Webhooks

Receive real-time notifications when statements are generated or spend thresholds are crossed.

Overview

Webhooks send HTTP POST requests to your endpoint when events occur. Configure them in Settings > Webhooks in the dashboard.

Event types

Event typeTrigger
statement.generatedA usage statement is generated for a customer (manual or scheduled).
usage.threshold_reachedA customer's spend crosses the threshold configured in statement settings.

These are the only two webhook events currently supported.

Payload format

Every webhook POST includes:

  • Content-Type: application/json
  • X-Dexcost-Signature header (HMAC-SHA256 of the body using your webhook secret)

statement.generated

Fires when a usage statement is created — either manually via the API or automatically on your configured billing cycle.

{
  "event_type": "statement.generated",
  "workspace_id": "ws-abc123",
  "statement_id": "stmt-xyz789",
  "customer_id": "acme-corp",
  "period_start": "2026-03-01",
  "period_end": "2026-04-01",
  "summary": {
    "total_cost_usd": "470.25",
    "total_tasks": 1234,
    "margin_pct": "52.5"
  },
  "fetch_url": "/v1/api/statements/stmt-xyz789",
  "timestamp": "2026-04-01T00:05:00Z"
}

Use fetch_url to retrieve the full statement with line items, per-service breakdowns, and margin data.

usage.threshold_reached

Fires when a customer's running spend in the current period crosses the threshold you configured in Settings > Statements > Spend Threshold.

{
  "event_type": "usage.threshold_reached",
  "workspace_id": "ws-abc123",
  "customer_id": "acme-corp",
  "current_spend_usd": "512.30",
  "threshold_usd": "500.00",
  "period": "monthly",
  "period_start": "2026-04-01",
  "timestamp": "2026-04-15T14:30:00Z"
}

Signature verification

Every request includes an X-Dexcost-Signature header. Verify it to ensure the webhook came from dexcost.

The signature is HMAC-SHA256(raw_request_body, your_webhook_secret) encoded as hex.

import hmac
import hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Retry behavior

If your endpoint returns a non-2xx status code, dexcost retries with exponential backoff:

AttemptDelay
1st retry10 seconds
2nd retry60 seconds
3rd retry5 minutes

After 3 failed attempts, the delivery is marked as failed. You can view delivery history in Settings > Webhooks.

Slack integration

If your webhook URL points to a Slack incoming webhook (hooks.slack.com), dexcost automatically formats the payload as a Slack Block Kit message instead of raw JSON.

Example Slack message for statement.generated:

📊 Statement Generated
Customer: acme-corp
Period: Mar 1 — Apr 1, 2026
Total cost: $470.25 | Tasks: 1,234

On this page