New:Socket for Asana Is Now Available.Learn more
Get Started

@grantex/sdk

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@grantex/sdk

TypeScript SDK for the Grantex delegated authorization protocol

Source
npmnpm
Version
0.3.7
Version published
Weekly downloads
2.3K
499.23%
Maintainers
1
Weekly downloads
 
Created
Source

@grantex/sdk

TypeScript SDK for the Grantex delegated authorization protocol — OAuth 2.0 for AI agents.

npm version License

Homepage | Docs | API Reference | Sign Up Free | GitHub

Installation

npm install @grantex/sdk

Quick Start

import { Grantex, verifyGrantToken } from '@grantex/sdk';

const grantex = new Grantex({ apiKey: 'YOUR_API_KEY' });

// 1. Register an agent
const agent = await grantex.agents.register({
  name: 'Email Assistant',
  description: 'Reads and sends email on behalf of users',
  scopes: ['email:read', 'email:send'],
});

// 2. Request authorization
const { consentUrl } = await grantex.authorize({
  agentId: agent.id,
  userId: 'usr_01J...',
  scopes: ['email:read', 'email:send'],
});
// Redirect the user to consentUrl — they approve in plain language

// 3. Exchange authorization code for a grant token
// (your redirect callback receives the `code` after user approves)
const token = await grantex.tokens.exchange({ code, agentId: agent.id });
console.log(token.grantToken);  // RS256-signed JWT
console.log(token.scopes);     // ['email:read', 'email:send']
console.log(token.grantId);    // 'grnt_01J...'

// 4. Verify the grant token offline (no network call)
const grant = await verifyGrantToken(token.grantToken, {
  jwksUri: 'https://api.grantex.dev/.well-known/jwks.json',
});
console.log(grant.principalId);  // 'usr_01J...'

// 5. Revoke when done
await grantex.tokens.revoke(grant.tokenId);

Configuration

const grantex = new Grantex({
  apiKey: 'gx_....',              // or set GRANTEX_API_KEY env var
  baseUrl: 'https://api.grantex.dev', // default
  timeout: 30000,                 // request timeout in ms (default: 30s)
});
OptionTypeDefaultDescription
apiKeystringprocess.env.GRANTEX_API_KEYAPI key for authentication
baseUrlstringhttps://api.grantex.devBase URL of the Grantex API
timeoutnumber30000Request timeout in milliseconds

PKCE Support

The SDK includes built-in PKCE (Proof Key for Code Exchange) support using the S256 method for secure authorization flows:

import { Grantex, generatePkce } from '@grantex/sdk';

const grantex = new Grantex({ apiKey: 'YOUR_API_KEY' });

// 1. Generate a PKCE challenge
const pkce = generatePkce();
// pkce.codeVerifier       — random 43-char string (keep secret)
// pkce.codeChallenge      — SHA-256 hash of verifier (send to server)
// pkce.codeChallengeMethod — 'S256'

// 2. Pass the challenge when requesting authorization
const { consentUrl } = await grantex.authorize({
  agentId: 'ag_01J...',
  userId: 'usr_01J...',
  scopes: ['files:read'],
  codeChallenge: pkce.codeChallenge,
  codeChallengeMethod: pkce.codeChallengeMethod,
});

// 3. Exchange the code with the verifier
const token = await grantex.tokens.exchange({
  code: 'auth_code_from_redirect',
  agentId: 'ag_01J...',
  codeVerifier: pkce.codeVerifier,
});

API Reference

Authorization

grantex.authorize(params)

Initiate the delegated authorization flow. Returns a consent URL to redirect the user to.

const request = await grantex.authorize({
  agentId: 'ag_01J...',
  userId: 'usr_01J...',
  scopes: ['files:read', 'email:send'],
  expiresIn: '24h',          // optional
  redirectUri: 'https://...' // optional
});

console.log(request.consentUrl);     // redirect user here
console.log(request.authRequestId);  // track the request
console.log(request.expiresAt);      // ISO 8601 timestamp

Returns: AuthorizationRequest

FieldTypeDescription
authRequestIdstringUnique ID for this authorization request
consentUrlstringURL to redirect the user to for consent
agentIdstringThe agent requesting authorization
principalIdstringThe user being asked for consent
scopesstring[]Requested scopes
expiresAtstringWhen the request expires (ISO 8601)
statusstring'pending', 'approved', 'denied', or 'expired'

Agents

grantex.agents.register(params)

Register a new AI agent.

const agent = await grantex.agents.register({
  name: 'Code Review Bot',
  description: 'Reviews pull requests and suggests improvements',
  scopes: ['repo:read', 'pr:comment'],
});

grantex.agents.get(agentId)

const agent = await grantex.agents.get('ag_01J...');

grantex.agents.list()

const { agents, total } = await grantex.agents.list();

grantex.agents.update(agentId, params)

const agent = await grantex.agents.update('ag_01J...', {
  name: 'Updated Name',
  scopes: ['repo:read', 'pr:comment', 'pr:approve'],
});

grantex.agents.delete(agentId)

await grantex.agents.delete('ag_01J...');

Grants

grantex.grants.get(grantId)

const grant = await grantex.grants.get('grnt_01J...');

grantex.grants.list(params?)

const { grants, total } = await grantex.grants.list({
  agentId: 'ag_01J...',       // optional filter
  principalId: 'usr_01J...',  // optional filter
  status: 'active',           // 'active' | 'revoked' | 'expired'
  page: 1,
  pageSize: 20,
});

grantex.grants.revoke(grantId)

await grantex.grants.revoke('grnt_01J...');

grantex.grants.delegate(params)

Create a delegated sub-agent grant (per SPEC Section 9).

const delegation = await grantex.grants.delegate({
  parentGrantToken: 'eyJhbG...',
  subAgentId: 'ag_02K...',
  scopes: ['files:read'],         // must be subset of parent scopes
  expiresIn: '1h',                // optional, cannot exceed parent
});

console.log(delegation.grantToken); // new JWT for the sub-agent
console.log(delegation.grantId);

grantex.grants.verify(token)

Verify a grant token via the API (online verification with real-time revocation check).

const verified = await grantex.grants.verify('eyJhbG...');
console.log(verified.principalId);
console.log(verified.scopes);

Tokens

grantex.tokens.exchange(params)

Exchange an authorization code for a grant token. This is the standard way to obtain a grant token after the user approves the consent request.

const token = await grantex.tokens.exchange({
  code: 'auth_code_from_redirect',  // from your redirect callback
  agentId: 'ag_01J...',
});

console.log(token.grantToken);   // RS256-signed JWT — pass this to your agent
console.log(token.grantId);      // grant record ID
console.log(token.scopes);       // granted scopes
console.log(token.expiresAt);    // ISO 8601 expiry
console.log(token.refreshToken); // for token refresh

Returns: ExchangeTokenResponse

FieldTypeDescription
grantTokenstringSigned RS256 JWT — the agent's bearer credential
grantIdstringGrant record ID
scopesstring[]Scopes the user approved
expiresAtstringToken expiry (ISO 8601)
refreshTokenstringRefresh token for obtaining new grant tokens

grantex.tokens.verify(token)

Online token verification with revocation status.

const result = await grantex.tokens.verify('eyJhbG...');
if (result.valid) {
  console.log(result.scopes);     // ['files:read']
  console.log(result.principal);  // 'usr_01J...'
  console.log(result.agent);      // 'ag_01J...'
  console.log(result.grantId);
  console.log(result.expiresAt);
}

grantex.tokens.revoke(tokenId)

Revoke a token by its JTI. Blocklisted in Redis immediately; all sub-delegated tokens are also invalidated.

await grantex.tokens.revoke('tok_01J...');

Offline Token Verification

verifyGrantToken(token, options)

Verify a grant token offline using the published JWKS. No API call needed — signature is verified locally using RS256.

import { verifyGrantToken } from '@grantex/sdk';

const grant = await verifyGrantToken('eyJhbG...', {
  jwksUri: 'https://api.grantex.dev/.well-known/jwks.json',
  requiredScopes: ['files:read'],   // optional — rejects if missing
  audience: 'https://myapp.com',    // optional — validates aud claim
});

Returns: VerifiedGrant

FieldTypeDescription
tokenIdstringUnique token ID (JWT jti claim)
grantIdstringGrant record ID
principalIdstringUser who authorized the grant (sub claim)
agentDidstringAgent's DID (agt claim)
developerIdstringDeveloper org ID (dev claim)
scopesstring[]Granted scopes (scp claim)
issuedAtnumberIssued-at timestamp (seconds since epoch)
expiresAtnumberExpiry timestamp (seconds since epoch)
parentAgentDidstring?Parent agent DID (delegation only)
parentGrantIdstring?Parent grant ID (delegation only)
delegationDepthnumber?Delegation depth (0 = root)

Audit

grantex.audit.log(params)

Log an auditable action taken by an agent.

const entry = await grantex.audit.log({
  agentId: 'ag_01J...',
  grantId: 'grnt_01J...',
  action: 'email:send',
  metadata: { to: 'user@example.com', subject: 'Hello' },
  status: 'success',   // 'success' | 'failure' | 'blocked'
});

grantex.audit.list(params?)

const { entries, total } = await grantex.audit.list({
  agentId: 'ag_01J...',
  action: 'email:send',
  since: '2026-01-01T00:00:00Z',
  until: '2026-02-28T23:59:59Z',
  page: 1,
  pageSize: 50,
});

grantex.audit.get(entryId)

const entry = await grantex.audit.get('aud_01J...');
console.log(entry.hash);      // SHA-256 hash for tamper evidence
console.log(entry.prevHash);   // previous entry hash (chain integrity)

Webhooks

grantex.webhooks.create(params)

const webhook = await grantex.webhooks.create({
  url: 'https://myapp.com/webhooks/grantex',
  events: ['grant.created', 'grant.revoked', 'token.issued'],
});
console.log(webhook.secret); // HMAC secret for signature verification

grantex.webhooks.list()

const { webhooks } = await grantex.webhooks.list();

grantex.webhooks.delete(webhookId)

await grantex.webhooks.delete('wh_01J...');

Webhook Signature Verification

import { verifyWebhookSignature } from '@grantex/sdk';

// In your webhook handler
verifyWebhookSignature(requestBody, signatureHeader, webhookSecret);

Policies

Define fine-grained access control rules for agents.

grantex.policies.create(params)

const policy = await grantex.policies.create({
  name: 'Block after hours',
  effect: 'deny',
  priority: 10,
  scopes: ['email:send'],
  timeOfDayStart: '18:00',
  timeOfDayEnd: '08:00',
});

grantex.policies.list()

const { policies, total } = await grantex.policies.list();

grantex.policies.get(policyId) / update(policyId, params) / delete(policyId)

const policy = await grantex.policies.get('pol_01J...');

await grantex.policies.update('pol_01J...', { effect: 'allow' });

await grantex.policies.delete('pol_01J...');

Compliance

grantex.compliance.getSummary(params?)

const summary = await grantex.compliance.getSummary({
  since: '2026-01-01T00:00:00Z',
  until: '2026-02-28T23:59:59Z',
});
console.log(summary.agents);        // { total, active, suspended, revoked }
console.log(summary.grants);        // { total, active, revoked, expired }
console.log(summary.auditEntries);  // { total, success, failure, blocked }

grantex.compliance.exportGrants(params?)

const { grants, total } = await grantex.compliance.exportGrants({
  status: 'active',
});

grantex.compliance.exportAudit(params?)

const { entries, total } = await grantex.compliance.exportAudit({
  since: '2026-01-01T00:00:00Z',
  agentId: 'ag_01J...',
});

grantex.compliance.evidencePack(params?)

Generate a full SOC 2 / GDPR evidence pack with audit chain integrity verification.

const pack = await grantex.compliance.evidencePack({
  framework: 'soc2',   // 'soc2' | 'gdpr' | 'all'
  since: '2026-01-01T00:00:00Z',
});

console.log(pack.chainIntegrity.valid);          // true
console.log(pack.chainIntegrity.checkedEntries);  // 1042
console.log(pack.summary);
console.log(pack.grants);
console.log(pack.auditEntries);
console.log(pack.policies);

Anomaly Detection

grantex.anomalies.detect()

Run anomaly detection across all agents.

const { anomalies, total } = await grantex.anomalies.detect();
// anomaly types: 'rate_spike' | 'high_failure_rate' | 'new_principal' | 'off_hours_activity'

grantex.anomalies.list(params?)

const { anomalies } = await grantex.anomalies.list({
  unacknowledged: true,  // only open anomalies
});

grantex.anomalies.acknowledge(anomalyId)

const anomaly = await grantex.anomalies.acknowledge('anom_01J...');

Billing

grantex.billing.getSubscription()

const sub = await grantex.billing.getSubscription();
console.log(sub.plan);             // 'free' | 'pro' | 'enterprise'
console.log(sub.status);           // 'active' | 'past_due' | 'canceled'
console.log(sub.currentPeriodEnd); // ISO 8601 or null

grantex.billing.createCheckout(params)

const { checkoutUrl } = await grantex.billing.createCheckout({
  plan: 'pro',
  successUrl: 'https://myapp.com/billing/success',
  cancelUrl: 'https://myapp.com/billing/cancel',
});
// Redirect user to checkoutUrl

grantex.billing.createPortal(params)

const { portalUrl } = await grantex.billing.createPortal({
  returnUrl: 'https://myapp.com/settings',
});

SCIM 2.0 Provisioning

Sync users from your identity provider.

Token Management

// Create a SCIM bearer token
const { token, id, label } = await grantex.scim.createToken({
  label: 'Okta SCIM integration',
});
// token is returned once — store it securely

const { tokens } = await grantex.scim.listTokens();

await grantex.scim.revokeToken('scimtok_01J...');

User Operations

// List provisioned users
const { Resources, totalResults } = await grantex.scim.listUsers({
  startIndex: 1,
  count: 100,
});

// Create a user
const user = await grantex.scim.createUser({
  userName: 'alice@example.com',
  displayName: 'Alice',
  emails: [{ value: 'alice@example.com', primary: true }],
});

// Get / Replace / Patch / Delete
const user = await grantex.scim.getUser('scimusr_01J...');

await grantex.scim.replaceUser('scimusr_01J...', { userName: 'alice@new.com' });

await grantex.scim.updateUser('scimusr_01J...', [
  { op: 'replace', path: 'active', value: false },
]);

await grantex.scim.deleteUser('scimusr_01J...');

SSO (OIDC)

grantex.sso.createConfig(params)

const config = await grantex.sso.createConfig({
  issuerUrl: 'https://accounts.google.com',
  clientId: 'xxx.apps.googleusercontent.com',
  clientSecret: 'GOCSPX-...',
  redirectUri: 'https://myapp.com/auth/callback',
});

grantex.sso.getConfig() / deleteConfig()

const config = await grantex.sso.getConfig();
await grantex.sso.deleteConfig();

grantex.sso.getLoginUrl(org)

const { authorizeUrl } = await grantex.sso.getLoginUrl('dev_01J...');
// Redirect user to authorizeUrl

grantex.sso.handleCallback(code, state)

const { email, name, sub, developerId } = await grantex.sso.handleCallback(code, state);

Error Handling

All errors extend GrantexError:

import {
  GrantexError,          // base class
  GrantexApiError,       // API returned an error (has statusCode, body, requestId)
  GrantexAuthError,      // 401/403 — invalid or missing API key
  GrantexTokenError,     // token verification failed (invalid signature, expired, etc.)
  GrantexNetworkError,   // network failure (timeout, DNS, connection refused)
} from '@grantex/sdk';

try {
  await grantex.agents.get('ag_invalid');
} catch (err) {
  if (err instanceof GrantexAuthError) {
    console.error('Auth failed:', err.statusCode);     // 401 or 403
    console.error('Request ID:', err.requestId);
  } else if (err instanceof GrantexApiError) {
    console.error('API error:', err.statusCode, err.body);
  } else if (err instanceof GrantexNetworkError) {
    console.error('Network error:', err.message, err.cause);
  }
}

Requirements

  • Node.js 18+
  • ESM ("type": "module" in your package.json, or use dynamic import())

Scope Enforcement (v0.3.1)

Enforce tool-level permissions on any connector — define your own manifests or use the 53 pre-built ones.

import { Grantex, ToolManifest, Permission } from '@grantex/sdk';

const grantex = new Grantex({ apiKey: 'gx_...' });

// Define a manifest for any connector — no dependency on Grantex to add support
grantex.loadManifest(new ToolManifest({
  connector: 'my-crm',
  tools: { search: Permission.READ, create_deal: Permission.WRITE, delete_account: Permission.DELETE },
}));

const result = await grantex.enforce({ grantToken: token, connector: 'my-crm', tool: 'delete_account' });
// result.allowed = false — "write scope does not permit delete operations"

Features:

  • enforce() — verify JWT + check tool permission via manifest, <1ms
  • wrapTool() — auto-enforce on LangChain tools
  • enforceMiddleware() — Express/Fastify HTTP middleware
  • Define custom manifests for any connector: inline, from JSON, or auto-generated via CLI
  • 53 pre-built manifests included (Salesforce, HubSpot, Jira, Stripe, SAP, S3, and 47 more)
  • Permission hierarchy: admin > delete > write > read
  • Permissive mode for migration (enforceMode: 'permissive')

Full Guide | API Reference

Grantex Ecosystem

PackageDescription
grantexPython SDK
@grantex/langchainLangChain integration
@grantex/autogenAutoGen integration
@grantex/vercel-aiVercel AI SDK integration
grantex-crewaiCrewAI integration
grantex-openai-agentsOpenAI Agents SDK integration
grantex-adkGoogle ADK integration
@grantex/mcpMCP server for Claude Desktop / Cursor / Windsurf
@grantex/cliCommand-line tool

License

Apache 2.0

Keywords

grantex

FAQs

Package last updated on 08 Apr 2026

Related posts