Batch & IntegrationsWebhooks

Webhooks

Signed events for finished or failed batch jobs, usage thresholds and expiring API keys — endpoint registration, event subscriptions, HMAC-SHA256 signature verification, retries, and auto-disable rules.

Register an endpoint

Webhooks push metadata-only events to your HTTPS endpoint. Registration requires the opt-in webhooks:manage scope — or use the Webhooks page of the dashboard (workspace admins and owners):

curl -sS -X POST https://api.transmute.403fin.io/v1/webhooks \
  -H "Authorization: Bearer $TRANSMUTE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/hooks/transmute", "events": ["job.completed", "usage.threshold"]}'
# → {"id": "...", "events": [...], "secret": "whsec_..."}   secret shown ONCE

GET /v1/webhooks lists endpoints; DELETE /v1/webhooks/{id} removes one. The whsec_ secret is displayed once at creation, like API keys. The URL must be public https://; hosts that resolve to private or loopback addresses are refused.

Choose your events

events is optional — omit it to receive job.completed only.

EventSent whenBody
job.completeda batch job that names this endpoint ("webhook": "<id>") finishes — completed, failed or partialtype, jobId, status, counts, createdAt, completedAt
job.failedthat job failed outright (every item failed). Sent instead of job.completed when you subscribe to it, never bothsame shape, "type": "job.failed"
usage.thresholdyour live usage crosses 75%, 90% or 100% of your plan's included volume — once per threshold per billing period (paid plans)type, threshold, periodStart, periodEnd, plan
key.expiringone of your API keys is within 7 days, then within 1 day, of its expirytype, keyId, prefix, expiresAt

usage.threshold deliberately carries no usage figures or amounts — read them from GET /v1/usage. key.expiring names the key by id and its non-secret prefix only.

Verify every delivery

Each delivery is signed:

X-Transmute-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>
X-Transmute-Event: job.completed      # or job.failed, usage.threshold, key.expiring
X-Transmute-Delivery: <id>          # stable across retries — dedupe on it

Verification:

  1. Compute HMAC-SHA256(key = the full secret string including the "whsec_" prefix, message = t + "." + raw request body bytes), lowercase hex.
  2. Compare against v1 constant-time.
  3. Reject timestamps more than 5 minutes from your clock (replay guard).

Verify over the raw received bytes — parse the JSON only after the signature checks out. The SDKs ship a verifier (Go, TypeScript, Python).

Retries and auto-disable

BehaviorValue
Success criterionAny 2xx from your endpoint
Retry ladder0s, 1m, 5m, 30m, 2h — 5 attempts max
DedupeX-Transmute-Delivery is stable across retries
Auto-disable10 consecutively exhausted deliveries disable the endpoint
Re-enableDelete and re-create the endpoint

The dashboard's Webhooks page shows the last 20 deliveries of each endpoint — event, attempts, last HTTP status and timing (never the payload).

Event contents

Every body carries ids, statuses, thresholds and timing — never message content, usage figures or money. Fetch results via GET /v1/jobs/{id} with your API key; the webhook is a doorbell, not a data channel.