> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://api.docs.gooclaim.com/llms.txt.
> For full documentation content, see https://api.docs.gooclaim.com/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api.docs.gooclaim.com/_mcp/server.

# Webhooks

Gooclaim pushes **webhooks** to your configured URL whenever a workflow
transitions state. Use webhooks to keep your CMS in sync, trigger downstream
automations, or feed your own dashboards.

## How webhooks work

```
Gooclaim Outbound Engine  ──HTTPS POST──▶  https://yourcms.example.com/gooclaim/webhook
                                            │
                                            ▼
                              Your endpoint returns 200 OK
                              within 5 seconds, or Gooclaim retries.
```

Webhooks are signed with **HMAC-SHA256** so you can verify they really came
from Gooclaim.

## Setup

You configure the webhook URL once per tenant via the Console UI (or via
the Tenant Config API if you have admin scope). You also receive a shared
**signing secret** at configuration time — store it somewhere safe.

## Event envelope

Every webhook payload uses the same envelope:

```json
{
  "event_id": "evt_01HXYZ...",
  "event_type": "workflow.completed",
  "tenant_id": "tnt_xyz",
  "occurred_at": "2026-05-20T10:14:25Z",
  "data": {
    "workflow_id": "wf_abc123",
    "workflow_type": "claim-status",
    "claim_id_hash": "sha256:..."
  }
}
```

Headers:

| Header                       | Purpose                                   |
| ---------------------------- | ----------------------------------------- |
| `X-Gooclaim-Event`           | Event type (also in body for convenience) |
| `X-Gooclaim-Signature`       | HMAC-SHA256 over the raw body             |
| `X-Gooclaim-Timestamp`       | UNIX timestamp when we signed             |
| `X-Gooclaim-Idempotency-Key` | Use this to dedupe retries on your side   |

## Event catalog

| Event type                  | Fires when                                                        |
| --------------------------- | ----------------------------------------------------------------- |
| `workflow.started`          | A workflow begins (any of the three)                              |
| `workflow.consent_required` | Claimant has no consent on file; Gooclaim is asking               |
| `workflow.consent_granted`  | Claimant gave DPDP consent                                        |
| `workflow.completed`        | Workflow finished happily                                         |
| `workflow.policy_blocked`   | Policy Gate blocked the output; needs human follow-up             |
| `workflow.timed_out`        | Pending Documents waited too long                                 |
| `pending_docs.uploaded`     | A document was uploaded — payload includes ref                    |
| `claim.fraud_suspect`       | 5+ NOT\_FOUND lookups on the same claim\_id                       |
| `operational_mode.changed`  | Your tenant's mode flipped (OPERATIONAL / RESTRICTED / SUSPENDED) |

More events are added in `v1.1`. Subscribe to specific event types via the
Console; the full event-type list is also queryable via
[the API](/api-reference).

## Signature verification

**Always verify** the signature before trusting the payload. Pseudo-code:

```python
import hmac
import hashlib

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

Reject the webhook if:

* the signature does not match
* `X-Gooclaim-Timestamp` is older than 5 minutes (replay protection)
* you have already processed this `X-Gooclaim-Idempotency-Key`

## Retries

Gooclaim retries failed deliveries with **exponential backoff**:

| Attempt | Delay after previous |
| ------- | -------------------- |
| 1       | (immediate)          |
| 2       | 30 seconds           |
| 3       | 2 minutes            |
| 4       | 10 minutes           |
| 5       | 1 hour               |
| 6       | 6 hours              |
| 7       | 24 hours (final)     |

After the final attempt, the event is moved to a dead-letter queue. You can
replay dead-lettered events from the Portal.

A delivery is considered successful if your endpoint responds with `2xx`
within **5 seconds**. `3xx`, `4xx`, `5xx`, and timeouts all count as failures.

Do not block in your webhook handler. **Acknowledge quickly** (200 OK), then
process asynchronously. A slow handler will cause retries to pile up and you
will receive duplicate events.

## Idempotency

Always treat webhooks as **at-least-once delivery**. Use the
`X-Gooclaim-Idempotency-Key` header to dedupe — store it for at least 7 days
and reject duplicates.

## Testing webhooks locally

For local development, expose your endpoint via `ngrok` or `cloudflared` and
configure the public URL in your tenant settings. Gooclaim retries on TLS
failures, so use a real HTTPS tunnel — `localhost` will not work.

## Next: explore the full API

Head to the [API Reference](/api-reference) for the complete endpoint catalog.