Privacy & Redaction
How @ledgergate/ledgergate-sdk protects your users' data — what is collected, what is redacted, and how to configure privacy controls.
Design Philosophy
The SDK is privacy-by-default. Every privacy protection described on this page is active out of the box — no configuration required to enable them. You only need to configure privacy options if you want to relax a protection (e.g. allowing a specific header through) or strengthen it (e.g. providing a custom IP hash salt).
The SDK is also non-custodial. It never captures request or response bodies, never stores payment credentials, and never handles funds.
What Is Collected
The SDK collects the following metadata per request:
| Field | Notes |
|---|---|
| HTTP method | GET, POST, etc. |
| Request path | Query strings stripped |
| Response status code | e.g. 200, 402 |
| Latency (milliseconds) | Measured from first byte in to last byte out |
| Request headers | Sensitive headers redacted — see below |
| Client IP | Hashed with SHA-256, then truncated to 16 hex chars |
| x402 payment metadata | Address, amount, network, token, status (from headers/body) |
| SDK name and version |
What Is Never Collected
- Request bodies
- Response bodies (unless you explicitly attach one for x402 parsing)
- Raw IP addresses
- Query string parameters
- Any cryptographic material (private keys, payment secrets, macaroons)
Header Redaction
All request headers are passed through a redaction filter before being stored on the RequestContext or included in events. The following headers are always replaced with [REDACTED]:
| Header |
|---|
authorization |
cookie |
set-cookie |
x-api-key |
x-auth-token |
x-access-token |
x-csrf-token |
x-xsrf-token |
proxy-authorization |
www-authenticate |
Matching is case-insensitive. The redacted value [REDACTED] replaces only the header value — the header name itself is preserved in the event.
Allowing specific headers through
Use redaction.allowedHeaders to permit headers that would otherwise be redacted:
const sdk = createLedgergateSdk({
apiKey: process.env.LEDGERGATE_API_KEY!,
redaction: {
allowedHeaders: ["x-api-key"], // allow this through for correlation
},
});Caution: Only allowlist headers whose values are safe to store on the Ledger Gate servers. Never allowlist
authorizationorcookie.
Header normalisation
All header names are lowercased before storage. Array-valued headers (which HTTP/1.1 permits) are joined into a comma-separated string.
IP Address Hashing
When redaction.hashIp is true (the default), the SDK:
- Extracts the client IP from
X-Forwarded-For→X-Real-IP→ direct socket IP (in that priority order) - Concatenates your
ipHashSaltwith the raw IP string - Computes SHA-256 over the result
- Truncates the hex digest to 16 characters
The resulting clientIpHash (e.g. "3f2a1b9e0c7d4e5f") allows usage correlation without revealing identifiable addresses.
Disabling IP collection
Set redaction.hashIp: false to skip all IP extraction and hashing. No clientIpHash will be present on any event.
const sdk = createLedgergateSdk({
apiKey: process.env.LEDGERGATE_API_KEY!,
redaction: {
hashIp: false,
},
});Custom hash salt
The default salt is an internal constant shared across all SDK installations. For stronger privacy guarantees, provide a unique salt per deployment:
const sdk = createLedgergateSdk({
apiKey: process.env.LEDGERGATE_API_KEY!,
redaction: {
ipHashSalt: process.env.IP_HASH_SALT!, // random secret, min 16 chars recommended
},
});With a custom salt, hashes from your deployment cannot be correlated with hashes from any other deployment — even if they tracked the same IP.
Sampling
Sampling is a complementary privacy control. With sampleRate: 0.1, only 10% of requests are tracked at all. Sampling is evaluated at the very start of the middleware — unsampled requests produce zero events and zero data collection.
const sdk = createLedgergateSdk({
apiKey: process.env.LEDGERGATE_API_KEY!,
sampleRate: 0.5, // track 50% of traffic
});See Configuration — sampleRate for details.
Low-Level API
The privacy utilities are exported directly if you need them outside the middleware context:
import {
extractClientIp,
hashIp,
isSensitiveHeader,
redactHeaders,
} from "@ledgergate/ledgergate-sdk";
// Extract the best-guess client IP from headers
const ip = extractClientIp(req.headers, req.socket.remoteAddress);
// Hash it
const hashed = hashIp(ip!, "my-custom-salt");
// Check a single header
const isSensitive = isSensitiveHeader("authorization"); // true
// Redact a headers object
const safe = redactHeaders(req.headers, ["x-tenant-id"]);| Export | Signature |
|---|---|
extractClientIp | (headers, directIp?) => string | undefined |
hashIp | (ip, salt?) => string (16-char hex) |
isSensitiveHeader | (name) => boolean |
redactHeaders | (headers, allowlist?) => Record<string, string> |