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

# NodeJS

# Node.js SDK

```bash theme={null}
npm install @keverdjs/node
```

Requires Node 18+. Zero runtime dependencies.

## Initialize + verify

```ts theme={null}
import { Keverd } from '@keverdjs/node';

const keverd = new Keverd({
  secretKey: process.env.KEVERD_SECRET_KEY!, // kv_sk_live_… or kv_sk_test_…
  // baseUrl: 'https://api.keverd.com',
  // timeoutMs: 30000,
});

const result = await keverd.verify(eventId);

if (result.action === 'block') {
  // reject
} else if (result.action === 'soft_challenge' || result.action === 'hard_challenge') {
  // step-up auth
} else {
  // allow
}
```

Maps to `POST https://api.keverd.com/v2/verify` with header `X-Secret-API-Key`.

## Express

```ts theme={null}
import express from 'express';
import { Keverd } from '@keverdjs/node';

const app = express();
const keverd = new Keverd({ secretKey: process.env.KEVERD_SECRET_KEY! });

app.post('/login', express.json(), async (req, res) => {
  const { eventId } = req.body;
  const risk = await keverd.verify(eventId);

  if (risk.action === 'block') {
    return res.status(403).json({ error: 'Blocked', reasons: risk.reasons });
  }

  res.json({ ok: true, visitorId: risk.visitor_id });
});
```

## Webhooks

```ts theme={null}
app.post(
  '/webhooks/keverd',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const event = keverd.webhooks.constructEvent(
      req.body, // raw Buffer — do not JSON.parse first
      req.headers['x-keverd-signature'] as string,
      process.env.KEVERD_WEBHOOK_SECRET!, // whsec_…
    );

    if (event.type === 'verification.completed') {
      const verification = event.data.object; // same shape as verify()
    }

    res.sendStatus(200);
  },
);
```

See [Webhooks](/server/webhooks).

## Errors

| Class                  | When                                           |
| ---------------------- | ---------------------------------------------- |
| `KeverdError`          | Validation, network, timeout                   |
| `KeverdAPIError`       | Non-2xx (`statusCode`, `body`) — `402` = quota |
| `KeverdSignatureError` | Bad webhook signature                          |

## Response fields

`event_id`, `fingerprint`, `visitor_id`, `risk_score`, `recommendation`, `action`, `reason`, `reasons`, `score`, `trust_score`, `reputation_score`, `signals`, `smart_signals`, `created_at`, `country_code`, `country_name`, `page_url`, `page_origin`
