npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@openage-agekey/sdk

v1.1.0

Published

Official AgeKey SDK for age verification integration

Readme

@openage-agekey/sdk

Official AgeKey SDK for age verification integration.

Installation

npm i @openage-agekey/sdk
# or
pnpm add @openage-agekey/sdk
# or
yarn add @openage-agekey/sdk

Quick Start

Use AgeKey: Verify Age

Check if a user meets age requirements.

import { AgeKey } from '@openage-agekey/sdk';

// Initialize the client
const agekey = new AgeKey({
  clientId: 'ak_test_xxxx',        // Your App ID
  redirectUri: 'https://myapp.com/callback',
});

// 1. Build authorization URL
const { url, state, nonce } = agekey.useAgeKey.getAuthorizationUrl({
  ageThresholds: [13, 18, 21],     // Ages to verify
  // provenance: { allowed: ['/connect_id'], denied: ['/legacy/*'] },  // Optional filter
});

// Store state/nonce in session (needed to validate callback)
session.ageKeyState = state;
session.ageKeyNonce = nonce;

// Redirect user to AgeKey
window.location.href = url;
// 2. Handle callback (on your /callback route)
import { AgeKey, AccessDeniedError } from '@openage-agekey/sdk';

const agekey = new AgeKey({
  clientId: 'ak_test_xxxx',
  redirectUri: 'https://myapp.com/callback',
});

try {
  const result = agekey.useAgeKey.handleCallback(
    window.location.href,
    { state: session.ageKeyState, nonce: session.ageKeyNonce }
  );

  // Check age thresholds
  if (result.ageThresholds["18"]) {
    console.log("User is 18+");
  } else {
    console.log("User is under 18");
  }
} catch (error) {
  if (error instanceof AccessDeniedError) {
    console.log("User cancelled verification");
  }
}

Create AgeKey: Store Age Verification

Store age verification signals for users (server-side only).

import { AgeKey } from '@openage-agekey/sdk';

// Initialize with client secret (server-side only!)
const agekey = new AgeKey({
  clientId: 'ak_test_xxxx',
  clientSecret: 'sk_test_xxxx',    // Required for Create flow
  redirectUri: 'https://myapp.com/callback',
});

// 1. Initiate Create AgeKey flow
const { authUrl, requestUri, expiresIn } = await agekey.createAgeKey.initiate({
  method: 'id_doc_scan',           // Verification method used
  age: { date_of_birth: '2000-01-15' },
  verifiedAt: new Date(),
  verificationId: 'txn_123456',    // Your unique transaction ID
  provenance: '/connect_id',       // Required: origin of verification (see Provenance section)
});

// Redirect user to authUrl
res.redirect(authUrl);
// 2. Handle callback
const result = agekey.createAgeKey.handleCallback(callbackUrl);

if (result.success) {
  console.log("AgeKey created successfully!");
} else {
  console.log("Error:", result.error);
}

Upgrade Direct: Add Age Signal to Existing AgeKey

Add a new age signal to an existing AgeKey server-side, without WebAuthn. Requires the Use flow to be completed with enableUpgrade: true.

import { AgeKey } from '@openage-agekey/sdk';

// Initialize with client secret (server-side only!)
const agekey = new AgeKey({
  clientId: 'ak_test_xxxx',
  clientSecret: 'sk_test_xxxx',
  redirectUri: 'https://myapp.com/callback',
});

// 1. Start Use flow with enableUpgrade
const { url, state, nonce } = agekey.useAgeKey.getAuthorizationUrl({
  ageThresholds: [18],
  enableUpgrade: true,
});
// Store state/nonce, redirect user to url...
// 2. Handle callback — extract the authorization code
const result = agekey.useAgeKey.handleCallback(callbackUrl, { state, nonce });
const { code } = result; // present when enableUpgrade was used
// 3. Exchange code for access token (server-side)
const { accessToken } = await agekey.upgradeDirect.exchangeCode(code);

// 4. Upgrade the AgeKey with a new age signal
const upgradeResult = await agekey.upgradeDirect.upgrade(accessToken, {
  method: 'id_doc_scan',
  age: { date_of_birth: '2000-01-15' },
  verifiedAt: new Date(),
  verificationId: 'txn_789',
  provenance: '/connect_id',
});

if (upgradeResult.success) {
  console.log("AgeKey upgraded successfully!");
}

API Reference

AgeKey Class

Main client class for all AgeKey operations.

const agekey = new AgeKey({
  clientId: string,       // Required: Your App ID (ak_test_xxx or ak_live_xxx)
  clientSecret?: string,  // Optional: Your App Secret (server-side only)
  redirectUri: string,    // Required: Pre-registered callback URL
});

Properties:

  • agekey.useAgeKey - Use AgeKey namespace
  • agekey.createAgeKey - Create AgeKey namespace
  • agekey.upgradeDirect - Upgrade Direct namespace
  • agekey.isTestMode - Whether using test credentials
  • agekey.clientId - The client ID
  • agekey.redirectUri - The redirect URI

Use AgeKey Namespace

getAuthorizationUrl(options)

Build an authorization URL to redirect the user.

const { url, state, nonce } = agekey.useAgeKey.getAuthorizationUrl({
  ageThresholds: [18],            // Required: Ages to verify
  allowedMethods?: [...],         // Optional: Restrict verification methods
  verifiedAfter?: Date,           // Optional: Require recent verification
  overrides?: MethodOverridesMap, // Optional: per-method age_thresholds or min_age overrides
  provenance?: {                  // Optional: Filter by origin (allowed/denied patterns)
    allowed?: string[],
    denied?: string[],
  },
  enableCreate?: boolean,         // Optional: Show "create AgeKey" button if user has none
  enableUpgrade?: boolean,        // Optional: Allow upgrading an existing AgeKey
});

All method overrides accept an optional age_thresholds array that maps 1:1 to the root ageThresholds (by index). When using overrides.facial_age_estimation, either min_age or age_thresholds is required (per request-claims schema oneOf). The FacialAgeEstimationOverride type enforces this at compile time, and the SDK validates it at runtime.

handleCallback(callbackUrl, validation)

Validate the callback and extract age verification results.

const result = agekey.useAgeKey.handleCallback(callbackUrl, { state, nonce });
// result.ageThresholds: { "18": true, "21": false }
// result.subject: "user_123" (optional)
// result.code: "abc123" (present when enableUpgrade was used)
// result.raw: { ... } (full JWT payload)

Create AgeKey Namespace

pushAuthorizationRequest(options) (server-side)

Send a PAR request to initiate Create AgeKey flow.

const { requestUri, expiresIn } = await agekey.createAgeKey.pushAuthorizationRequest({
  method: 'id_doc_scan',
  age: { date_of_birth: '2000-01-15' },
  verifiedAt: new Date(),
  verificationId: 'txn_123',
  attributes?: { ... },          // Optional: Method-specific attributes
  provenance: string,            // Required: origin of verification (see AUTHORIZATION_PROVENANCE)
  enableUpgrade?: boolean,       // Optional: Allow upgrading existing AgeKey
});

getAuthorizationUrl(requestUri)

Build authorization URL from PAR response.

const url = agekey.createAgeKey.getAuthorizationUrl(requestUri);

initiate(options) (server-side)

Convenience method combining PAR + authorization URL.

const { authUrl, requestUri, expiresIn } = await agekey.createAgeKey.initiate({
  method: 'id_doc_scan',
  age: { date_of_birth: '2000-01-15' },
  verifiedAt: new Date(),
  verificationId: 'txn_123',
  provenance: '/connect_id',   // Required (see AUTHORIZATION_PROVENANCE)
});

Upgrade Direct Namespace

exchangeCode(code) (server-side)

Exchange an authorization code from the Use callback for an access token.

const { accessToken, tokenType, expiresIn } = await agekey.upgradeDirect.exchangeCode(code);

upgrade(accessToken, options) (server-side)

Add an age signal to an existing AgeKey using an access token.

const result = await agekey.upgradeDirect.upgrade(accessToken, {
  method: 'id_doc_scan',
  age: { date_of_birth: '2000-01-15' },
  verifiedAt: new Date(),
  verificationId: 'txn_123',
  provenance: '/connect_id',
  attributes?: { ... },          // Optional: Method-specific attributes
});
// result.success: true

Error Handling

The SDK provides typed errors for common scenarios:

import {
  AgeKeyError,           // Base error class
  StateMismatchError,    // CSRF protection triggered
  NonceMismatchError,    // Replay attack detected
  AccessDeniedError,     // User cancelled or denied
  InvalidTokenError,     // Malformed/expired token
  InvalidRequestError,   // Bad request parameters
  UnauthorizedClientError, // Invalid credentials
  ServerError,           // AgeKey server error
  NetworkError,          // Network connectivity issue
} from '@openage-agekey/sdk';

try {
  const result = agekey.useAgeKey.handleCallback(url, { state, nonce });
} catch (error) {
  if (error instanceof AccessDeniedError) {
    // User cancelled - show friendly message
  } else if (error instanceof StateMismatchError) {
    // Possible CSRF - restart flow
  } else if (error instanceof AgeKeyError) {
    // Other AgeKey error
    console.log(error.code, error.message, error.docsUrl);
  }
}

Environment Detection

The SDK automatically detects test vs live environment from your credentials:

  • ak_test_* / sk_test_* → Test environment
  • ak_live_* / sk_live_* → Live environment
const agekey = new AgeKey({ clientId: 'ak_test_xxx', ... });
console.log(agekey.isTestMode); // true

Verification Methods

Supported methods for Create AgeKey:

| Method | Description | |--------|-------------| | id_doc_scan | Government ID document scan | | payment_card_network | Credit/debit card verification | | facial_age_estimation | AI-based facial age estimation | | email_age_estimation | Email-based age signals | | digital_credential | Digital identity credentials | | national_id_number | National ID number verification |

Provenance

Provenance identifies the origin of the age verification technology. The SDK supports it in both flows.

Create AgeKey: Setting provenance

Each age signal you create must include a provenance value; it is required by the authorization-detail schema and the SDK does not default it.

Valid values are defined by the AgeKey authorization-detail schema. Use the exported constant for type-safe options (e.g. in dropdowns):

import { AgeKey, AUTHORIZATION_PROVENANCE, type AuthorizationProvenance } from '@openage-agekey/sdk';

// AUTHORIZATION_PROVENANCE is the list of allowed values:
// "/connect_id", "/stripe", "/inicis", "/singpass", "/privy", "/spruce_id",
// "/verify_my", "/privately", "/veratad/internal", "/veratad/trinsic", "/veratad/cra", "/veratad/roc",
// "/yoti", "/meta"

const { authUrl } = await agekey.createAgeKey.initiate({
  method: 'digital_credential',
  age: { at_least_years: 18 },
  verifiedAt: new Date(),
  verificationId: 'txn_abc',
  provenance: '/veratad/roc',   // required
});

Use AgeKey: Filtering by provenance

When verifying age (Use flow), you can restrict which age signals are accepted by allowed and denied provenance patterns (request-claims schema). Denied takes precedence over allowed. Use a * suffix for prefix matching (e.g. '/veratad/*').

const { url, state, nonce } = agekey.useAgeKey.getAuthorizationUrl({
  ageThresholds: [18],
  provenance: {
    allowed: ['/connect_id', '/veratad/*'],   // Only accept these origins (max 10)
    denied: ['/legacy/*'],                    // Exclude these (max 10)
  },
});

If you omit provenance, all provenances are accepted (no filter).

Method Overrides

When verifying age (Use flow), you can provide per-method overrides. Each override can include min_age, age_thresholds, verified_after, and attributes.

age_thresholds maps 1:1 to the root ageThresholds by index: override.age_thresholds[i] is the minimum age for that method needed to satisfy root threshold i. Its length must equal the root ageThresholds length.

const { url, state, nonce } = agekey.useAgeKey.getAuthorizationUrl({
  ageThresholds: [13, 18],
  overrides: {
    // facial_age_estimation requires either min_age or age_thresholds (oneOf)
    facial_age_estimation: {
      min_age: 20,                         // raise the bar for this method
      attributes: { on_device: true },
    },
    // age_thresholds example: [15, 20] means this method needs 15+ for the 13 threshold, 20+ for the 18 threshold
    payment_card_network: {
      age_thresholds: [15, 20],
    },
  },
});

Age Formats

When creating an AgeKey, specify age in one of these formats:

// Exact date of birth
age: { date_of_birth: '2000-01-15' }

// Exact years
age: { years: 24 }

// At least N years (minimum age)
age: { at_least_years: 21 }

TypeScript Support

Full TypeScript support with exported types:

import type {
  AgeKeyConfig,
  UseAgeKeyOptions,
  UseAgeKeyResult,
  CreateAgeKeyOptions,
  PARResult,
  UpgradeDirectOptions,
  ExchangeTokenResult,
  UpgradeDirectResult,
  VerificationMethod,
  AgeSpec,
  AuthorizationProvenance,
  MethodOverride,
  MethodOverridesMap,
  FacialAgeEstimationOverride,
} from '@openage-agekey/sdk';
import { AUTHORIZATION_PROVENANCE } from '@openage-agekey/sdk';  // list of valid provenance values

Documentation

License

MIT