# Certn API Documentation - Webhooks

> Source: https://centric-api-docs.certn.co/#webhooks
> Interactive docs: https://centric-api-docs.certn.co/#webhooks

## Webhooks

The Certn platform can notify your systems when particular events occur by sending webhooks. You can configure webhook URLs in the Integrations area of the Client Portal.

### Event Types

| Event Code | Description |
|------------|-------------|
| `CASE_STATUS_CHANGED` | The status of a case has changed. Track progress during a case's lifecycle. |
| `CHECK_STATUS_CHANGED` | The status of an individual check has changed. Receive real-time updates on check progress. |
| `CASE_REPORT_READY` | The case report you requested has been generated and is ready to retrieve. |
| `CASE_INPUT_CLAIMS_AUTOMATICALLY_GENERATED` | A case has new input claims automatically generated by Certn (only for some quickscreen checks). |

### Webhook Payload

```json
{
  "id": "e50b8c4f-9a95-40a0-886a-37aa21ea078e",
  "event_type": "CASE_STATUS_CHANGED",
  "object_id": "2f64d134-1c54-4028-8e8b-9cfa7bd8011c",
  "object_type": "CASE"
}
```

### Endpoint Verification (Required)

**Webhook Validation Requirement**: You **must** implement endpoint verification within **10 seconds**. If verification fails, webhook delivery will be disabled.

When you add a webhook URL, our system sends a GET request with a `challenge` parameter. Your app must echo back the challenge value as the response body.

**Flask:**
```python
@app.get('/certn-webhook/')
def verify():
    return request.args["challenge"], {
        "Content-Type": "text/plain",
        "X-Content-Type-Options": "nosniff",
    }
```

**Express:**
```javascript
app.get('/certn-webhook', (req, res) => {
  res.set('Content-Type', 'text/plain');
  res.set('X-Content-Type-Options', 'nosniff');
  res.send(req.query.challenge);
});
```

### Payload Signature Verification (Recommended)

Webhook requests include an `X-Signature` header containing an HMAC-SHA256 signature of the request body. The signing key is provided when you create the webhook configuration.

```python
from hashlib import sha256
import hmac

@app.post("/certn-webhook/")
def webhook():
    signature = request.headers.get("X-Signature")
    expected = hmac.new(WEBHOOK_SECRET, request.data, sha256).hexdigest()
    if not hmac.compare_digest(signature, expected):
        abort(403)

    payload = request.json
    # Process webhook...
    return "", 200
```

### Best Practices

- **Respond quickly**: Return a 200 response within 10 seconds. Process webhook data asynchronously in a background job.
- **Retry behavior**: Failed deliveries are retried with exponential backoff (30s, 90s, 270s, etc.) for approximately 2 hours.
- **Handle out-of-order delivery**: Due to retries, you may receive webhooks out of order. Design your system to handle this.
- **Deduplicate events**: Each webhook has a unique `id`. Store processed IDs to avoid processing the same event twice.

---

## Additional Resources

- [Interactive Documentation](https://centric-api-docs.certn.co)
- [OpenAPI Specification](https://centric-api-docs.certn.co/openapi.yaml)
- [All Reference Docs](https://centric-api-docs.certn.co/reference/)

*Generated from Certn API Documentation*