Quickstart
Record your first consent grant with the TypeScript SDK. You create an API key, install @zyton/pip, and run one script that records a user's consent, checks it, revokes it and reads your audit trail. It takes about 10 minutes.
Before you start
- Node.js 20.19 or later (or 22.12 or later) and npm.
- A Zyton developer account. Create a free account, or sign in if you have one.
1. Create an API key
Open API keys, give the key a name, keep Sandbox selected and select Create key. Copy the secret as soon as it appears: we only show it once.
Sandbox keys start with pip_sk_test_. They use the same workspace as live keys, but their consent grants are kept apart: a sandbox key never sees, checks or revokes a grant recorded with a live key.
2. Install the SDK
Make a new project and install the SDK, plus tsx to run TypeScript.
mkdir zyton-quickstart && cd zyton-quickstart
npm init -y
npm install @zyton/pip
npm install --save-dev tsx3. Set your key
Keep the key in an environment variable, never in your code. It is a secret: use it only on your server.
export PIP_API_KEY="pip_sk_test_..." # the sandbox key you just copied4. Save the script
Save this as quickstart.ts. It runs as written.
import { PipClient } from '@zyton/pip';
import { withConsentGate } from '@zyton/pip/consent-gate';
async function main(): Promise<void> {
// 1. Your secret key from the API keys page. PipClient swaps it for a short-lived
// access token on first use and renews it for you: you never handle tokens.
const pip = new PipClient({ apiKey: process.env.PIP_API_KEY });
const me = await pip.authenticate();
console.log(`Signed in with a ${me.keyEnv} key`);
// 2. Your user agreed, in your app, to get order updates by email. Record that consent
// with your evidence. subjectRef is your own id for the user, never an email address.
const { grant } = await pip.consent.recordGrant({
subjectRef: 'user_8412',
purpose: 'Order updates by email',
dataCategories: ['email'],
operations: ['process'],
evidence: { consentTextVersion: 'checkout-consent-v1' },
});
console.log(`Recorded grant ${grant.grantId} (${grant.status}, ${grant.attestation})`);
// 3. Check before you use the data.
const check = { subjectRef: 'user_8412', operation: 'process', dataCategories: ['email'] } as const;
console.log('Allowed:', await pip.consent.checkConsent(check));
// 4. Or gate the code that uses it: it runs only while a grant covers it, and each
// decision is written to your tamper-evident audit trail.
const sendOrderUpdate = withConsentGate(
{ consent: pip.consent, actorEntityId: me.entityId!, audit: pip.createAuditWriter() },
{ toolName: 'send_order_update', ...check },
async (orderId: string) => `Order update for ${orderId} sent`,
);
console.log(await sendOrderUpdate('order_1001'));
// 5. The user withdrew consent: revoke the grant. Checks and gated code now fail closed.
await pip.consent.revokeGrant(grant.grantId);
console.log('Allowed:', await pip.consent.checkConsent(check));
await sendOrderUpdate('order_1002').catch((err: Error) => console.log(`Blocked: ${err.name}`));
// 6. Read your audit trail, newest first: the gate's decisions.
const { items } = await pip.audit.query({ entityId: me.entityId, limit: 3 });
for (const event of items) {
console.log(event.timestamp.toISOString(), event.eventType, event.eventData.decision ?? '');
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
Step by step, it:
- Creates a
PipClientwith your key. The client exchanges the key for an access token that lasts 5 minutes, renews it before it expires, and sends the key nowhere else. - Records a developer-attested grant: your statement that user
user_8412agreed, in your app, to get order updates by email.subjectRefis your own id for the user. - Checks the grant with
checkConsent, which asks the API every time and never caches. - Wraps the code that uses the data with
withConsentGate, so it only runs while a grant covers it and every decision goes to your audit trail. - Revokes the grant, the way you would when the user withdraws, and shows that the check and the gated code now refuse.
- Reads your audit trail, newest first.
5. Run it
npx tsx quickstart.tsYou see something like this (your ids and times differ):
Signed in with a sandbox key
Recorded grant 019a4f3c-5e2b-7d41-9c0a-3b8e2f6d1a77 (active, developer_attested)
Allowed: true
Order update for order_1001 sent
Allowed: false
Blocked: ConsentDeniedError
2026-11-01T10:15:02.391Z mcp.tool.call deny
2026-11-01T10:15:02.207Z mcp.tool.call.result
2026-11-01T10:15:02.165Z mcp.tool.call allowRun it again whenever you like: after a revoke, the same input records a new grant.
Good to know
- Keys and tokens. Never send the key itself in an
Authorizationheader: every API refuses it. The SDK exchanges it for a short-lived token atPOST https://api.zyton.ai/oauth/token. A revoked or rotated key stops working within 5 minutes, when the last token it was exchanged for expires. - What a key can't do. A key is for the API only. Key tokens get
403on billing and on GDPR data subject request (DSAR) routes, and they can't manage keys, passwords, MFA or sessions. Those need a person signed in to this portal. - Your organisation's trail. Every grant and revoke is also recorded as a
consent.grantedorconsent.revokedevent. Workspace admins and operators can read the whole trail under Audit log; a key reads only the events of its own entity.
If something goes wrong
InvalidCredentialsError: the key is wrong, revoked or rotated. Copy it again, or rotate it on API keys. After a refusal the SDK waits a minute before it sends that key again; a newPipClientstarts fresh.ValidationError: something was refused before any request was sent, such as a missingPIP_API_KEY, an email address assubjectRefor an emptydataCategorieslist. The message says what.- Other errors carry the HTTP status and the API's error code in
err.context. The HTTP API overview lists every code and what to do about it.
Next steps
- The SDK reference: every consent call, the consent gate for AI agent tools, configuration and errors.
- Approval requests: instead of recording consent on your word, ask the end user to approve on a Zyton-hosted screen, then check the grant their approval creates.
- The API reference and the HTTP API overview, to call the API from another language.
- When your integration is ready, create a live key (
pip_sk_live_…) on API keys and keep it in a secrets manager.