# Navattic Webhooks

Navattic (interactive product demos) sends a webhook whenever a visitor session in one of your
demos is closed. Payloads are not signed. The only authentication is an `Authorization` header
that Navattic sends **only when you configure one on the webhook**: `Basic <credentials>` or
`Bearer <token>`.

## When to Use This Skill

* How do I receive Navattic webhooks?
* How do I verify the Navattic `Authorization` header (Basic or Bearer)?
* Does Navattic sign webhook payloads? (No: shared credential header only)
* Why does my Navattic webhook endpoint return 401?
* How do I handle the `session_closed` event for visitors and accounts?

## Verification (core)

Hookdeck's Navattic source compares the **whole** `Authorization` header value to the
configured key, and so do the examples. Store the value exactly as Navattic sends it, scheme
prefix included (for example `Bearer abc123`). Don't strip, parse or base64-decode it:

```javascript
const crypto = require('crypto');

// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
  const ha = crypto.createHash('sha256').update(String(a)).digest();
  const hb = crypto.createHash('sha256').update(String(b)).digest();
  return crypto.timingSafeEqual(ha, hb);
}

function verifyNavatticRequest(headers, expected = process.env.NAVATTIC_AUTHORIZATION) {
  if (!expected) return false;                // never accept when unconfigured
  const received = headers['authorization'];  // full value, e.g. "Bearer abc123"
  return Boolean(received) && safeEqual(received, expected);
}

```

Return `401` when this fails (missing header or mismatch), before reading the body. Read the
body raw (`express.raw({ type: '*/*' })`) so any content type works, and parse it only after the
check. Python and Next.js equivalents are in [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/navattic-webhooks/references/verification.md).

**Security note:** a static shared credential authenticates the sender, not the body, and gives
no replay protection (there is no signature and no timestamp). Use HTTPS only, and rotate the
credential in Navattic and in `NAVATTIC_AUTHORIZATION` if it leaks.

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

## HTTP Methods

Navattic's page doesn't name the HTTP method, so the examples accept `GET`, `POST`, `PUT`,
`PATCH` and `DELETE` on the route, check the credential first for every method, and treat an
empty body as nothing to process (`200`). Hookdeck's Navattic source pre-selects `POST` without
managing the method, so any other method the sender uses must also be allowed on the source.

## Event Types

| `eventType` | Sent when | `data` holds |
| --- | --- | --- |
| `session_closed` (visitor) | A visitor session is marked closed | `{ session, endUser, companyAccount }` (`companyAccount` can be `null`) |
| `session_closed` (account) | Same, for an account event | The company account object itself (`id`, `name`, `websiteDomain`, ...) |

The envelope is `{ eventType, timestamp, data }`; `timestamp` is the ISO 8601 session close time.
`eventType` is always `session_closed` today. Dispatch on `eventType`, then tell visitor and
account events apart by the shape of `data` (the examples check for `data.session`).

## Environment Variables

```bash
NAVATTIC_AUTHORIZATION=Bearer your-token   # the full Authorization value, prefix included

```

## Local Development

```bash
npx hookdeck-cli listen 3000 navattic --path /webhooks/navattic

```

No account required. Use the printed URL as the webhook URL in Navattic.

## Hookdeck Source Setup

Hookdeck's Navattic source type (`NAVATTIC`, labelled "Navattic") shows this note, and it
applies to the examples too: Paste the full Authorization value Navattic sends, including the "Basic " or "Bearer " prefix.

## Resources

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/navattic-webhooks/references/overview.md) - Session events, payload fields, request headers
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/navattic-webhooks/references/setup.md) - Adding the webhook in Navattic and configuring the credential
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/navattic-webhooks/references/verification.md) - Header check in Node, Python and Next.js, gotchas
* [examples/](https://github.com/hookdeck/webhook-skills/tree/main/skills/navattic-webhooks/examples/) - Runnable Express, Next.js and FastAPI handlers with tests