zykay-sdk
v1.0.2
Published
ZYKAY SDK - Simplified partner integration for age verification
Downloads
344
Maintainers
Readme
@zykay/sdk
Official ZYKAY SDK for Node.js - Simplified age verification integration.
Transform your ZYKAY Widget integration from 150+ lines of HMAC code to just 5 lines.
Installation
npm install @zykay/sdk
# or
pnpm add @zykay/sdk
# or
yarn add @zykay/sdkQuick Start
Express (5 lines!)
import express from 'express';
import { zykay } from '@zykay/sdk';
const app = express();
const sdk = zykay({ partnerId: 'partner_xyz', secret: process.env.ZYKAY_SECRET! });
app.use(express.json());
app.post('/api/zykay/exchange', sdk.expressMiddleware());Next.js App Router (4 lines!)
// app/api/zykay/exchange/route.ts
import { zykay } from '@zykay/sdk';
const sdk = zykay({ partnerId: 'partner_xyz', secret: process.env.ZYKAY_SECRET! });
export const POST = sdk.nextHandler();Direct API Usage
import { zykay } from '@zykay/sdk';
const sdk = zykay({
partnerId: 'partner_xyz',
secret: process.env.ZYKAY_SECRET!,
});
// Exchange grant code for pass token
const result = await sdk.exchange('g_abc123...');
console.log(result.pass_token); // "p_xyz789..."
console.log(result.expires_in); // 14400 (4 hours)
// Later: Introspect the pass token
const status = await sdk.introspect(result.pass_token);
if (status.active) {
console.log(status.attributes?.age_over_18); // true
}Configuration
const sdk = zykay({
// Required
partnerId: 'partner_xyz', // From ZYKAY dashboard
secret: process.env.ZYKAY_SECRET!, // HMAC secret from dashboard
// Optional
apiUrl: 'https://api.zykay.com', // Default API URL
timeout: 30000, // Request timeout (ms)
});Frontend Integration
Use the ZYKAY Widget loader on your frontend:
<!-- Your HTML page -->
<script src="https://widget-app.zykay.com/loader/loader.js"></script>
<button onclick="ZykayWidget.open()">Verify Age</button>
<script>
ZykayWidget.init({
partnerId: 'partner_xyz',
onVerified: function(result) {
// result.grant_code is sent to your backend
fetch('/api/zykay/exchange', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ grant_code: result.grant_code })
})
.then(r => r.json())
.then(data => {
console.log('Pass token:', data.pass_token);
// Store pass_token for future introspection
});
}
});
</script>API Reference
zykay(config)
Create a new SDK instance with middleware helpers.
Parameters:
config.partnerId(string, required) - Your partner ID from the ZYKAY dashboardconfig.secret(string, required) - HMAC secret from ZYKAY dashboardconfig.apiUrl(string, optional) - API base URL (default:https://api.zykay.com)config.timeout(number, optional) - Request timeout in milliseconds (default: 30000)
Returns: ZykaySDKWithMiddleware
sdk.exchange(grantCode)
Exchange a grant code for a pass token.
Parameters:
grantCode(string) - The grant code from the widget (starts withg_)
Returns: Promise<ExchangeResponse>
{
pass_token: string; // Pass token for introspection (starts with "p_")
expires_in: number; // Token lifetime in seconds (default: 14400 = 4 hours)
token_type: 'Bearer'; // Token type
}sdk.introspect(passToken)
Check if a pass token is still valid and get user attributes.
Parameters:
passToken(string) - The pass token to introspect (starts withp_)
Returns: Promise<IntrospectResponse>
{
active: boolean; // Whether the token is valid
scope?: string; // 'age_verification' | 'identity_verification'
exp?: number; // Expiration timestamp (ms)
iat?: number; // Issuance timestamp (ms)
sub?: string; // Subject identifier (flow ID)
attributes?: {
age_over_18: boolean;
verification_method: 'france_identite';
verified_at: number;
// Additional attributes based on scope
};
}sdk.expressMiddleware(options?)
Create Express middleware for grant code exchange.
Options:
getGrantCode(function, optional) - Custom grant code extractoronError(function, optional) - Custom error handler
Example:
// Default: reads from req.body.grant_code
app.post('/api/zykay/exchange', sdk.expressMiddleware());
// Custom grant code location
app.post('/api/verify', sdk.expressMiddleware({
getGrantCode: (req) => req.body.verification_code
}));sdk.nextHandler(options?)
Create Next.js App Router handler for grant code exchange.
Example:
// app/api/zykay/exchange/route.ts
export const POST = sdk.nextHandler();sdk.expressIntrospectMiddleware()
Create Express middleware for token introspection.
app.post('/api/zykay/introspect', sdk.expressIntrospectMiddleware());sdk.nextIntrospectHandler()
Create Next.js handler for token introspection.
// app/api/zykay/introspect/route.ts
export const POST = sdk.nextIntrospectHandler();Error Handling
The SDK throws ZykayError for all API errors:
import { zykay, ZykayError } from '@zykay/sdk';
try {
const result = await sdk.exchange('g_invalid');
} catch (error) {
if (error instanceof ZykayError) {
console.log(error.message); // Human-readable message
console.log(error.code); // Error code (e.g., 'GRANT_INVALID')
console.log(error.status); // HTTP status code
console.log(error.correlationId); // For debugging with ZYKAY support
}
}Error Codes
| Code | Status | Description |
|------|--------|-------------|
| INVALID_REQUEST | 400 | Missing or invalid parameters |
| INVALID_GRANT | 400 | Invalid grant code format |
| GRANT_INVALID | 401 | Grant code expired or already used |
| INVALID_TOKEN_FORMAT | 400 | Invalid pass token format |
| TIMEOUT | 408 | Request timed out |
| NETWORK_ERROR | 500 | Network connectivity issue |
Complete Examples
Express with Error Handling
import express from 'express';
import { zykay, ZykayError } from '@zykay/sdk';
const app = express();
app.use(express.json());
const sdk = zykay({
partnerId: process.env.ZYKAY_PARTNER_ID!,
secret: process.env.ZYKAY_SECRET!,
});
// Exchange endpoint
app.post('/api/zykay/exchange', sdk.expressMiddleware({
onError: (error, req, res) => {
console.error('ZYKAY exchange failed:', error.code);
res.status(error.status).json({
success: false,
error: error.code,
});
}
}));
// Introspect endpoint
app.post('/api/zykay/introspect', sdk.expressIntrospectMiddleware());
// Custom endpoint using SDK directly
app.post('/api/verify-age', async (req, res) => {
try {
const { grant_code } = req.body;
const exchange = await sdk.exchange(grant_code);
// Store pass_token in your user session
req.session.passToken = exchange.pass_token;
// Immediately introspect to get age status
const status = await sdk.introspect(exchange.pass_token);
res.json({
success: true,
age_over_18: status.attributes?.age_over_18 || false,
});
} catch (error) {
if (error instanceof ZykayError) {
res.status(error.status).json({ success: false, error: error.code });
} else {
res.status(500).json({ success: false, error: 'INTERNAL_ERROR' });
}
}
});
app.listen(3000);Next.js with Multiple Routes
// app/api/zykay/exchange/route.ts
import { zykay } from '@zykay/sdk';
const sdk = zykay({
partnerId: process.env.ZYKAY_PARTNER_ID!,
secret: process.env.ZYKAY_SECRET!,
});
export const POST = sdk.nextHandler();// app/api/zykay/introspect/route.ts
import { zykay } from '@zykay/sdk';
const sdk = zykay({
partnerId: process.env.ZYKAY_PARTNER_ID!,
secret: process.env.ZYKAY_SECRET!,
});
export const POST = sdk.nextIntrospectHandler();// app/api/verify/route.ts - Custom verification logic
import { zykay, ZykayError } from '@zykay/sdk';
const sdk = zykay({
partnerId: process.env.ZYKAY_PARTNER_ID!,
secret: process.env.ZYKAY_SECRET!,
});
export async function POST(req: Request) {
try {
const { grant_code } = await req.json();
const exchange = await sdk.exchange(grant_code);
const status = await sdk.introspect(exchange.pass_token);
return Response.json({
verified: true,
age_over_18: status.attributes?.age_over_18,
pass_token: exchange.pass_token,
});
} catch (error) {
if (error instanceof ZykayError) {
return Response.json(
{ verified: false, error: error.code },
{ status: error.status }
);
}
return Response.json(
{ verified: false, error: 'INTERNAL_ERROR' },
{ status: 500 }
);
}
}TypeScript Support
The SDK is written in TypeScript and includes full type definitions:
import {
zykay,
ZykaySDK,
ZykayError,
ZykayConfig,
ExchangeResponse,
IntrospectResponse,
TokenAttributes,
} from '@zykay/sdk';Security
- All requests are signed with HMAC-SHA256
- Grant codes are single-use and expire after 5 minutes
- Pass tokens expire after 4 hours by default
- Never expose your
secretin client-side code - Store secrets in environment variables
Support
- Documentation: https://zykay.com/docs
- Email: [email protected]
- Issues: https://github.com/zykay/sdk/issues
License
MIT
