Skip to Content
Launching the open-source gateway

Data webhooks

Send spans, traces, scores, and billing events to your own endpoint.

A data webhook sends a JSON POST to your URL each time an event happens in Respan, such as a span being logged or your credit balance running low. Use it to copy spans into your own warehouse or to trigger alerts in your systems.

To get alerts when a metric crosses a threshold, use a monitor instead. Monitors have their own webhook destinations.

Create a webhook

Open Webhooks

Go to Settings › Integrations, open the Webhooks tab, and click Create webhook.

Fill in the webhook

Enter a Name and the full endpoint URL. Pick an Event type, choose the API key whose traffic it covers, and click Create.

The Create webhook dialog with Name, URL, Event type set to span, and API key set to Acme default

Copy the secret

The dialog now shows the Webhook secret. Copy it and store it on your server, so you can verify deliveries.

To see it again later, click the webhook and click the eye icon next to Webhook secret. The refresh icon rotates it, and the old secret stops working right away.

Use the Status switch in the list to pause a webhook. To delete one, open the row’s menu and click Delete.

Event types

Event typeSent whenevent_type in the payload
spanA span is loggedrequest_log
completed traceA trace finishestrace_completed
scoreAn evaluator score is recordedon_eval_result_ingested
User budget limit reachedOne of your users goes over their budgetcustomer_budget_limit_reached
Credit low balance threshold reachedYour credit balance drops below the warning amount on Billingcredit_low_balance_threshold_reached

Events that come from requests only include traffic sent with the webhook’s API key. Create one webhook per event type.

What Respan sends

Each delivery is a POST with a JSON body: the event type, plus the event’s data. For a span, data is the span as Respan logged it, with fields such as model, prompt_tokens, completion_tokens, cost, latency, and customer_identifier.

JSON
{ "event_type": "credit_low_balance_threshold_reached", "data": { "organization_id": "5f1d2c7e-8a41-4d07-9c52-3b6e95a0c1d4", "organization_name": "Acme", "current_balance": 48.72, "warning_threshold": 50.0, "timestamp": "2026-09-30T17:24:05.312481+00:00" } }

Each request carries these headers:

HeaderValue
X-Keywordsai-SignatureHex HMAC-SHA256 of the raw request body, keyed with your webhook secret
Keywordsai-TimestampWhen the delivery was sent, in Unix seconds
X-Signature-Secret-Typewh_secret

Check the signature against the raw body before you parse it:

Python
import hashlib import hmac import os def is_from_respan(raw_body: bytes, signature: str) -> bool: secret = os.environ["RESPAN_WEBHOOK_SECRET"].encode() expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature)

Delivery

  • Return a 2xx within 30 seconds. Queue slow work and respond first.
  • Failed deliveries aren’t retried. After 5 failures in a row, Respan pauses the webhook for 5 minutes and emails your organization’s owner. Events during the pause are dropped.
  • The URL must be publicly reachable. Private and internal addresses are blocked.
  • A Slack incoming webhook URL (hooks.slack.com) gets a formatted Slack message instead of the raw JSON.