# Codat Webhooks

[Codat](https://www.codat.io) is a business data API. Its webhooks report company and connection lifecycle events and data read and write results. Codat delivers them through **Svix** with the Standard Webhooks header names `webhook-id`, `webhook-timestamp` and `webhook-signature` (**not** `svix-*`). Legacy rule-based webhooks are deprecated and not covered.

## When to Use This Skill

* How do I receive Codat webhooks?
* How do I verify a Codat webhook signature?
* Where do I find my Codat webhook signing secret?
* How do I handle `company.created`, `connection.connected`, `read.completed` or `write.successful`?
* Why is my Codat `webhook-signature` verification failing?
* How do I dedupe Codat webhook retries?

## Verification (core)

| Header | Value |
| --- | --- |
| `webhook-id` | Unique message ID, the same on every retry |
| `webhook-timestamp` | Unix seconds of this delivery attempt |
| `webhook-signature` | `v1,<base64 HMAC-SHA256>`, space-separated entries (several during rotation) |

Signed content is `{webhook-id}.{webhook-timestamp}.{raw body}`. The key is the base64-**decoded** part of the endpoint's secret after `whsec_`. Each endpoint has its own secret. The examples use the `standardwebhooks` library (npm, PyPI), which enforces a 5-minute timestamp tolerance and compares in constant time. Hookdeck retries and replays resend the original `webhook-timestamp`, so the library rejects them once they are more than 5 minutes old. If you receive through Hookdeck and need late retries to pass, use the manual check in [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/codat-webhooks/references/verification.md) and drop or widen its timestamp window.

```javascript
const { Webhook } = require('standardwebhooks');

// rawBody: exact request body string, NOT re-serialised JSON
function verifyCodatWebhook(rawBody, headers, secret = process.env.CODAT_WEBHOOK_SECRET) {
  return new Webhook(secret).verify(rawBody, {
    'webhook-id': headers['webhook-id'],
    'webhook-timestamp': headers['webhook-timestamp'],
    'webhook-signature': headers['webhook-signature'],
  }); // returns the parsed event; throws → respond 400
}

```

Python: `from standardwebhooks.webhooks import Webhook`, then `Webhook(secret).verify(await request.body(), {...same mapping...})`. A dependency-free manual version is in [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/codat-webhooks/references/verification.md). In Express, read the body with `express.raw({ type: '*/*' })` so any content type verifies.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/codat-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/codat-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/codat-webhooks/examples/fastapi/).

## Common Event Types

| Event | Fired when |
| --- | --- |
| `company.created` | A company is created |
| `connection.created` | A data connection is created |
| `connection.connected` | A connection becomes connected |
| `read.completed` | A data read finishes |
| `write.successful` | A write to the data source succeeds |

> **Full list:** [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/codat-webhooks/references/overview.md) and [Codat's event types](https://docs.codat.io/using-the-api/webhooks/event-types).

## Delivery Semantics

* Dedupe on the `webhook-id` header, which is the same on every retry.
* Return a `2xx` quickly and process asynchronously.

## Environment Variables

```bash
CODAT_WEBHOOK_SECRET=whsec_xxxxx   # endpoint's signing secret; handlers fail closed (500) without it

```

Get it from the Codat Portal: **Monitor > Webhooks > Events** → your endpoint → **Signing secret**.

## Local Development

```bash
# Express / Next.js (use 8000 for FastAPI). No install or account required.
npx hookdeck-cli listen 3000 codat --path /webhooks/codat

```

Add the printed URL as an endpoint in the Codat Portal (**Monitor > Webhooks > Events**), choose event types, and create a company or connection to trigger events.

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/codat-webhooks/references/overview.md) - Event catalog and delivery semantics
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/codat-webhooks/references/setup.md) - Portal endpoint setup and signing secret
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/codat-webhooks/references/verification.md) - Library and manual verification, gotchas, debugging