@c15t/node-sdk: Node.js client for the c15t consent API
Typed client for hosted and self-hosted c15t backends. Check consent before sending email, link users after sign-in, export a user's consent records, publish legal document releases from CI and read banner experiment results.
c15t is used by 2,100+ sites, including expo.dev, zed.dev, unkey.dev, mintlify.com, and sazabi.com.
Key Features
- One
createC15tClient()call with an explicit backend URL. No environment variables are read - Methods resolve to
{ ok: true, data }or{ ok: false, error }and never reject. Error codes are typed per method - Key-only methods (
consents.check,subjects.list,experiments.summary,legalDocuments.publish) exist only on a client created with an API key - Input is validated before anything is sent, and response dates are
Dateobjects - Per-attempt timeouts and retries for network errors, timeouts and 408, 429, 500, 502, 503 and 504, honouring
Retry-After - A typed mock client in
@c15t/node-sdk/testing
Prerequisites
- Node.js 20.19 or later, or another runtime with
fetch,AbortSignal.anyandcrypto.randomUUID - A hosted c15t instance or a self-hosted backend
Installation
pnpm add @c15t/node-sdk
Usage
- Create a client with the URL where the backend is mounted, path included. Pass
apiKeyfor the key-only methods - Call a method and check
result.okbefore readingresult.data, or useunwrap(result)to throw the error instead
// server.ts
import { createC15tClient } from '@c15t/node-sdk';
const apiKey = process.env.C15T_API_KEY;
if (!apiKey) throw new Error('Set C15T_API_KEY');
const c15t = createC15tClient({
baseUrl: 'https://app.example.com/api/c15t',
apiKey,
});
const result = await c15t.consents.check({
externalId: user.id,
types: ['marketing_communications'],
});
if (result.ok && result.data.results.marketing_communications.hasConsent) {
await sendNewsletter(user);
} else if (!result.ok) {
console.error(result.error.code, result.error.requestId);
}
Documentation
See the documentation for guides, API reference, and examples.
Methods
| Method | API key |
|---|---|
consents.check({ externalId, types }) | Required |
subjects.identify(id, { externalId, identityProvider, identityToken }) | No; verified only with a key or token |
subjects.get(id, { types }) | No |
subjects.create(input) | No |
subjects.list({ externalId }) | Required |
legalDocuments.publish(type, { version, hash, effectiveDate }) | Required |
experiments.summary(id, { from, to, domain }) | Required |
status(), init(), manifest() | No |
Every method takes { signal, timeoutMs, headers, retry, requestId } as its last argument.
createIdentityToken(user, { signingKey }) is a separate export, not a client method. It signs a token locally for the browser's identify(), takes no call options, and throws a TypeError on invalid input.
Upgrading from v2
c15tClient() and the C15TClient class are replaced by createC15tClient(). Results replace ResponseContext, C15TError is now C15tError, and subjects.patch is now subjects.identify. See the migration guide.
Support
- Join our Discord community
- Open an issue on our GitHub repository
- Visit inth.com and use the chat widget
- Contact our support team via email [email protected]
Contributing
- Read the contribution guidelines before you open a pull request
- Follow the code of conduct
Security
Do not open a public issue for a security vulnerability. Report it privately through GitHub's vulnerability reporting. We examine every valid report.
- Do not share the vulnerability in public forums, issues, or pull requests
- Give the steps to reproduce it and the versions it affects
- Give us time to release a fix before you disclose it
License
Built by Inth