# Server SDK: consent on the backend

Read the consent decision in your server code and verify signed webhooks.

> Canonical: https://www.flowconsent.com/en/doc/server-sdk
> Last updated: 2026-07-29
## Why

The banner blocks the browser, but half of the processing starts server-side: GA4 Measurement Protocol, CRM sync, attribution cookies. `@flowconsent/server-sdk` reads the first-party cookie set by the banner (versioned v1 contract) and returns a typed decision — **denied by default** when the cookie is missing, unreadable or stale.

## Install

```sh
npm install @flowconsent/server-sdk
```

Zero dependencies, edge-compatible (Vercel, Cloudflare Workers, Node ≥ 18).

## Read the decision

```ts
import { readConsent } from '@flowconsent/server-sdk'

const decision = readConsent(request)
if (decision.can('analytics')) {
  // send the GA4 Measurement Protocol event
}
// decision.reason: 'ok', 'no_cookie', 'expired', 'version_mismatch'…
```

`decision.can('google-analytics')` also works per service. Pass `expectedConfigHash` (your banner's) to automatically invalidate choices made before a configuration change.

## Verify webhooks

Consent webhooks are signed (HMAC-SHA256, `X-FlowConsent-Signature` header, Stripe-style):

```ts
import { verifyWebhookSignature } from '@flowconsent/server-sdk'
const check = await verifyWebhookSignature(rawBody, signatureHeader, secret)
if (!check.valid) return new Response('invalid', { status: 400 })
```

The secret is shown once, when the webhook is created (app or MCP `configure_consent_webhook`).
