> ## Documentation Index
> Fetch the complete documentation index at: https://developers.resistant.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks (Svix)

Webhooks provide an alternative to polling by delivering HTTPS notifications to your callback endpoint when processing completes. Resistant AI uses **Svix** as the webhook delivery provider.

<Info>
  Webhooks are available subject to prior agreement and may involve an additional fee.
</Info>

<Warning>
  **Current limitation:** Webhooks are currently supported **only for Adaptive Decision** completion (the `/decision` result).\
  For fraud/quality/classification notifications, use **Polling** (default) or **Amazon SQS** (optional add-on).
</Warning>

***

## When to use webhooks (vs polling / SQS)

Use webhooks if you:

* Want an event-driven integration without Amazon SQS
* Already operate webhook receivers for other systems
* Prefer HTTP callbacks over queue-based delivery
* Need notifications specifically for **Adaptive Decision** completion

Use SQS if you:

* Are AWS-native and want queue-based scaling and durability
* Need notifications for **fraud / quality / classification** outputs

Use polling if you:

* Want the simplest integration and lowest operational complexity

***

## How it works (high level)

1. You provide Resistant AI with a **callback URL** (your public HTTPS endpoint).
2. Resistant AI (via Svix) sends a webhook when **Adaptive Decision** completes for a submission.
3. Your receiver verifies the webhook signature and acknowledges the event.
4. Your system fetches the full decision result from the Documents API:
   * `GET /v2/submission/{submission_id}/decision`

Svix retries delivery using exponential backoff if delivery fails.

***

## Setup requirements

To enable webhooks, you will provide:

* **Callback URL**: a public HTTPS endpoint that can receive `POST` requests
* **Signature verification**: you should verify Svix signatures (recommended)

After enablement, Resistant AI will configure your webhook endpoint and provide the signing secret / configuration details.

***

## Security: signature headers

Webhook requests include these headers:

* `webhook-id`
* `webhook-timestamp`
* `webhook-signature`

Verify signatures using Svix verification logic:

* validate the signature matches your expected signing secret
* validate timestamp tolerance to prevent replay attacks

**Example (Python, using Svix SDK):**

```python theme={null}
from svix.webhooks import Webhook

secret = "whsec_your_signing_secret"
wh = Webhook(secret)

# In your HTTP handler:
payload = request.body  # raw bytes
headers = {
    "webhook-id": request.headers["webhook-id"],
    "webhook-timestamp": request.headers["webhook-timestamp"],
    "webhook-signature": request.headers["webhook-signature"],
}
msg = wh.verify(payload, headers)  # raises if invalid
```

> Keep signature verification strict. Do not accept unsigned events.

***

## Events and payloads

Webhooks are delivered with an event object containing:

* `type`
* `version`
* `tenant_id`
* `payload`

### Supported event types

Your webhook integration currently receives:

* `documents.adaptive_decision.finished`

<Note>
  Fraud/quality/classification events are not currently delivered via webhooks.
</Note>

### Example payload: adaptive decision finished

This is an example shape. Always treat the webhook as a **notification**, then fetch the authoritative result from `/decision`.

```json theme={null}
{
  "type": "documents.adaptive_decision.finished",
  "version": 0,
  "tenant_id": "string",
  "payload": {
    "id": "submission_id",
    "status": "SUCCESS",
    "analysis_time": "string",
    "query_id": "string",
    "result_url": "/v2/submission/submission_id/decision"
  }
}
```

**What to do on receipt**

* Verify signature
* Deduplicate (see below)
* Call `GET {result_url}` (or build it from `submission_id`) to fetch the full decision payload

***

## Operational notes

### Retries and idempotency

Svix retries delivery using exponential backoff on failures.

Your receiver should be idempotent:

* treat webhooks as **at-least-once** delivery
* deduplicate using a stable key such as:
  * the `webhook-id` header, or
  * `(submission_id, event_type, version)` tuple

### Updating configuration

If you need to:

* update your callback URL, or
* rotate / update signing configuration,

contact your Resistant AI CSM / implementation contact.

***

## Testing

During onboarding, you can request a test event to validate delivery and signature verification.

***

## Troubleshooting

### Webhooks not arriving

* Confirm your callback URL is publicly reachable over HTTPS
* Check firewall/WAF rules and request logs on your side
* Confirm you have provided the correct endpoint to Resistant AI

### Signature verification failing

* Confirm you are using the correct signing secret for your endpoint
* Confirm your clock is accurate (timestamp validation can fail if system clock is skewed)
* Log `webhook-id`, `webhook-timestamp`, and `webhook-signature` for debugging

### Duplicate events

* Expect duplicates under retry conditions; implement idempotency and deduplication (see above)

### I need notifications for fraud/quality/classification

* Use **Polling** (default) or **Amazon SQS** (optional add-on), as webhooks currently notify only `/decision`.
