Skip to main content

Overview

The x402 protocol enables AI agents to pay for API resources using USDC on Base L2 with no login, no API key, and no subscription. @grantex/x402 adds the missing authorization layer — a Grantex Delegation Token (GDT) that proves the paying agent was authorized to spend. What x402 solves: Machine-to-machine payments. What Grantex adds: Proof that the payment was authorized — by whom, for what, how much, and when.

Install

npm install @grantex/x402

Quick Start

1. Issue a Delegation Token

A human principal issues a scoped GDT to their agent:
import { generateKeyPair, issueGDT } from '@grantex/x402';

const principal = generateKeyPair();
const agent = generateKeyPair();

const gdt = await issueGDT({
  agentDID: agent.did,
  scope: ['weather:read'],
  spendLimit: { amount: 10, currency: 'USDC', period: '24h' },
  expiry: '24h',
  signingKey: principal.privateKey,
});

2. Agent Makes Authorized Payments

The agent attaches the GDT to x402 payment requests:
import { createX402Agent } from '@grantex/x402';

const x402 = createX402Agent({
  gdt: gdtToken,
  paymentHandler: async (details) => {
    // Sign USDC transfer on Base L2
    return await payOnBase(details);
  },
});

// Automatic: request → 402 → pay → retry with GDT
const response = await x402.fetch('https://api.weather.xyz/forecast');

3. API Verifies Authorization

The API server requires a valid GDT alongside the x402 payment:
import express from 'express';
import { x402Middleware } from '@grantex/x402';

const app = express();

app.use('/api/weather', x402Middleware({
  requiredScopes: ['weather:read'],
  currency: 'USDC',
}));

app.get('/api/weather/forecast', (req, res) => {
  const { gdt } = req;
  res.json({
    forecast: 'sunny',
    authorizedBy: gdt.principalDID,
  });
});

How It Works

1. Principal ──── issueGDT() ────▶ GDT (W3C VC 2.0 JWT)

2. Agent ──── x402Agent.fetch() ─────────┤

3. API returns HTTP 402 ◀──── Payment Required

4. Agent pays via Base L2 ───────────────┤

5. Agent retries with Payment + GDT ─────┤

6. API ──── x402Middleware ──── verifyGDT()
   │                                     │
   ▼                                     ▼
   Response returned              Audit log entry
The GDT is a W3C Verifiable Credential 2.0 encoded as a JWT, signed with Ed25519. It encodes:
  • Who authorized the spend (principal DID)
  • What the agent can access (scoped permissions)
  • How much the agent can spend (spend limit + period)
  • When the authorization expires
  • Chain of delegation for multi-agent scenarios

GDT Token Structure

{
  "iss": "did:key:z6Mk...principal...",
  "sub": "did:key:z6Mk...agent...",
  "vc": {
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://grantex.dev/v1/x402"
    ],
    "type": ["VerifiableCredential", "GrantexDelegationToken"],
    "credentialSubject": {
      "id": "did:key:z6Mk...agent...",
      "scope": ["weather:read", "news:read"],
      "spendLimit": {
        "amount": 10,
        "currency": "USDC",
        "period": "24h"
      },
      "paymentChain": "base",
      "delegationChain": ["did:key:...principal..."]
    }
  },
  "iat": 1711036800,
  "exp": 1711123200,
  "jti": "550e8400-e29b-41d4-a716-446655440000"
}

API Reference

issueGDT(params)

Issue a signed Grantex Delegation Token.
agentDID
string
required
DID of the agent being delegated to.
scope
string[]
required
Array of resource:action scope strings (e.g., ['weather:read']).
spendLimit
SpendLimit
required
{ amount: number, currency: 'USDC' | 'USDT', period: '1h' | '24h' | '7d' | '30d' }
expiry
string
required
ISO 8601 duration (PT24H, P7D) or shorthand (24h, 7d) or datetime.
signingKey
Uint8Array
required
32-byte Ed25519 private key seed of the issuing principal.
delegationChain
string[]
Parent DIDs for sub-delegation chains.
paymentChain
string
default:"base"
Blockchain for payment authorization.
Returns: Promise<string> — The signed GDT JWT.

verifyGDT(token, context)

Verify a GDT against a request context. Checks signature, expiry, revocation, scope, and spend limit.
token
string
required
The GDT JWT to verify.
context.resource
string
required
The resource:action scope being requested.
context.amount
number
required
Spend amount for this request.
context.currency
Currency
required
'USDC' or 'USDT'.
Returns: Promise<VerifyResult>:
{
  valid: boolean;
  agentDID: string;
  principalDID: string;
  remainingLimit: number;
  scopes: string[];
  tokenId: string;
  expiresAt: string;
  error?: string;
}

createX402Agent(config)

Create an x402 fetch wrapper with automatic 402 → pay → retry handling.
const agent = createX402Agent({
  gdt: gdtToken,
  paymentHandler: async (details) => {
    // details: { amount, currency, recipientAddress, chain, memo? }
    return paymentProof;
  },
});

const response = await agent.fetch('https://api.example.com/data');

x402Middleware(options)

Express middleware for GDT verification.
OptionTypeDefaultDescription
requiredbooleantrueRequire GDT (403 if missing)
requiredScopesstring[]Scopes to enforce
currencyCurrency'USDC'Currency for verification
extractAmount(req) => numberCustom amount extractor

Revocation

Instantly revoke a GDT:
import { getRevocationRegistry } from '@grantex/x402';

const registry = getRevocationRegistry();
await registry.revoke(tokenId, 'agent compromised');

// All subsequent verifications will reject this token

Audit Log

All GDT operations are logged:
import { getAuditLog } from '@grantex/x402';

const log = getAuditLog();
const entries = await log.query({
  eventType: 'verification',
  limit: 50,
});

// Export for compliance
const all = await log.export();

Scope Matching

GrantedRequestedMatch
weather:readweather:readYes
weather:readweather:writeNo
weather:*weather:readYes
*anything:anythingYes

CLI

# Generate Ed25519 key pair
grantex-x402 keygen

# Issue a GDT
grantex-x402 issue --agent did:key:z6Mk... --scope weather:read --limit 10 --expiry 24h --key principal.key

# Verify a GDT
grantex-x402 verify <token> --resource weather:read --amount 0.001

# Revoke a GDT
grantex-x402 revoke <tokenId>

# Decode (inspect) a GDT
grantex-x402 decode <token>

Examples

See the examples directory for runnable demos:
  • x402-weather-api — Express server with x402 pricing + GDT enforcement
  • x402-agent-demo — Agent client that issues a GDT, pays, and fetches data

Security Considerations

  • Ed25519 signatures — GDTs are cryptographically signed; tampering invalidates the token
  • Scope enforcement — Agents can only access resources explicitly granted
  • Spend limits — Per-period spending caps prevent wallet drain
  • Instant revocation — Compromised tokens are rejected immediately
  • Unique token IDs — Every GDT has a UUID jti for replay protection
  • Audit trail — All issuance, verification, and revocation events are logged

Dependencies

PackagePurpose
@noble/ed25519Ed25519 key generation and signing
@noble/hashesSHA-512 for Ed25519
joseJWT encoding, signing, and verification