Skip to main content
After an agent pays for access, Key0 issues a signed JWT that the agent uses to call your protected endpoints. This page covers the classes and functions involved in creating, signing, and verifying those tokens.
Subscription plans only. Token issuance applies only to plan purchases. For route-based pay-per-call flows, fetchResourceCredentials is not called:
  • Embedded per-request — Key0 settles on-chain and calls next(), passing control to your route handler. No JWT is issued; req.key0Payment contains payment metadata.
  • Standalone per-request — Key0 settles on-chain and proxies the request to your backend via fetchResource/proxyTo. The backend’s response is returned directly as a ResourceResponse.
See Pay-Per-Request for the full per-request flow.

Token issuance flow

1

Challenge transitions to PAID

The ChallengeEngine verifies the on-chain payment and transitions the challenge from PENDING to PAID.
2

fetchResourceCredentials is called

Your callback receives the payment context:
3

Callback returns credentials

Your callback returns { token: string } (or any credential shape you define).
4

Challenge transitions to DELIVERED

The engine atomically transitions the challenge to DELIVERED.
5

AccessGrant is returned

The agent receives the signed JWT and uses it as a Bearer token on subsequent requests.

AccessTokenIssuer

The AccessTokenIssuer class handles JWT creation and verification. It supports two signing algorithms: HS256 (shared secret) and RS256 (RSA key pair).

Constructor

The constructor accepts either a plain string (backward-compatible) or a config object:
HS256 secrets must be at least 32 characters. The constructor throws immediately if the secret is shorter.

Config type

Methods

sign

Creates a signed JWT with the given claims and TTL.

verify

Verifies a token using the primary secret. HS256 only — RS256 tokens should be verified with validateKey0Token using the public key.

verifyWithFallback

Tries the primary secret first, then falls back to a list of previous secrets. Use this during secret rotation.

TokenClaims

Every Key0 JWT contains these custom claims alongside the standard iat and exp:

validateToken middleware

The validateToken function is a framework-agnostic utility that extracts and verifies a Bearer token from an Authorization header. The framework integrations (Express, Hono, Fastify) wrap this function into middleware.

Error handling

validateToken throws a Key0Error with the following codes:

validateKey0Token (lightweight validator)

If your backend service only needs to verify tokens and does not need the full SDK, use the standalone validator from @key0ai/key0/validator. It supports both HS256 and RS256 and has no blockchain dependencies.
The validator checks all required claims (sub, jti, resourceId, planId, txHash) and throws if any are missing.

HS256 vs RS256

Token issuance timeout

The ChallengeEngine wraps your fetchResourceCredentials callback in a Promise.race with a configurable timeout.
Timeouts are never retried. When fetchResourceCredentials times out, the engine throws TOKEN_ISSUE_TIMEOUT (HTTP 504) immediately and does not retry. This is intentional: Promise.race does not cancel the losing promise, so the original call may still be in flight. Retrying would risk spawning concurrent calls that could issue duplicate credentials.
For transient (non-timeout) errors, the engine retries up to tokenIssueRetries times with exponential backoff (500ms base delay — 500ms, 1s, 2s, and so on). If token issuance fails permanently, the challenge stays in the PAID state. The refund cron can pick it up and settle an on-chain refund automatically.