Skip to content

TypeScript API reference

Two SubEtha packages are published to npm; both are Apache-2.0, ESM-only, and require Node.js >= 20. The sections marked published 0.1.0 surface describe what was verified in the registry package. The later source-additions sections are based on the merged product source at 85fd50ac; they are not asserted to be present in the registry artifact until a new npm publication is independently verified. The exact official x402 package pins used below were manually checked against npm on 2026-08-07; that auxiliary observation is recorded in the repository’s registry-verification evidence.

applies to @subetha/x402-scheme 0.1.0 (npm, verified 2026-08-07)applies to @subetha/provider 0.1.0 (npm, verified 2026-08-07)

The facilitator daemon is not on this list on purpose: subetha-facilitator is the private/workspace-internal package under apps/facilitator; the separate @subetha/facilitator workspace library is also not published to npm (npm returns 404 for it — see Versions & compatibility). Both are operated from product repository source only.

@subetha/x402-scheme — payer-side scheme, types, fees

Section titled “@subetha/x402-scheme — payer-side scheme, types, fees”
Terminal window
npm install @subetha/[email protected] @x402/[email protected] @x402/[email protected] viem

The published 0.1.0 registry artifact’s documented surface contains three modules. The current source index below is cited for source reconciliation and re-exports five modules at 85fd50ac; its two additional history modules are listed separately as source additions and are not asserted as present in the published artifact. (src/index.ts)

export kind description
SUBETHA_SCHEME const the scheme identifier, "subetha-zerc20"
DEFAULT_EXPIRY_SKEW_SECONDS const clock-skew margin (5): clients treat expiresAt <= now + skew as expired
DEFAULT_LAST_BROADCAST_CUTOFF_SECONDS const self-transfer safety margin (30): refuse to broadcast a burn this close to expiry
MAX_REASONABLE_EPOCH_SECONDS const 1e11 — values at/above this cannot be unix seconds (milliseconds guard)
toNetwork(chainId) function CAIP-2 id for an EVM chain id (eip155:<chainId>)
parseNetwork(network) function parse a CAIP-2 eip155 id back to a chain id; throws on non-eip155 input
export kind description
SubethaFeeInfo interface fee disclosure { amount, bps } (payer-charged mode only; already included in amount)
SubethaExtra interface the scheme’s PaymentRequirements.extra: challengeNonce, expiresAt, helper?, deadline?, fee?
SubethaPermitPayload interface gasless payload: challengeNonce, payer, permit { value, nonce, deadline, v, r, s }, burnAuthSig
SubethaSelfTransferPayload interface fallback payload: challengeNonce, burnTxHash
parseSubethaRequirements(requirements) function validate + narrow an offer’s SubEtha fields (payTo, asset, amount, chainId, extra); throws a specific message on anything malformed
export kind description
SubethaSchemeClientOptions interface account (required), mode? ("permit" default | "self-transfer"), rpcUrl?, publicClient?, walletClient?, expirySkewSeconds?, lastBroadcastCutoffSeconds?
SubethaSchemeClient class x402 v2 scheme handler for subetha-zerc20 (structurally implements the official SchemeNetworkClient). Members: scheme, createPaymentPayload(x402Version, requirements), burnTxFor(challengeNonce) (self-transfer mode), lastRequirements

In the default "permit" mode the client fails fast when an offer lacks extra.helper — it never silently degrades to a gas-paying transfer. Construction requires rpcUrl or an injected publicClient.

export kind description
ParsedFee interface { fee, bps, quoted, listPrice } (all amounts as bigint base units)
parseFee(requirements) function typed view of an offer’s fee disclosure; undefined when the offer carries no fee field
feeAwarePolicy() function a PaymentPolicy for the official x402 client that ranks offers by the quoted total (the payer’s true spend), never by list price

Current source additions (not asserted as published npm surface)

Section titled “Current source additions (not asserted as published npm surface)”

The merged SubEtha source at 85fd50ac additionally re-exports the following history-related helpers from @subetha/x402-scheme:

export source role
HistoryBinding, createHistoryBinding(), verifyHistoryBinding() src/history-binding.ts bind an offer and idempotency key to a history record
PayerHistoryStatus, PayerHistoryAttestation, verifyPayerHistoryAttestation() src/history-attestation.ts verify a facilitator proof before exposing a payer claim

These source exports must not be treated as available from the currently published 0.1.0 artifact until npm publication is re-verified.

const scheme = new SubethaSchemeClient({ account, mode: "permit", rpcUrl });
const client = new x402Client().register("eip155:31337", scheme);
const fetchWithPay = wrapFetchWithPayment(fetch, client);

Import x402Client from @x402/core/client and wrapFetchWithPayment from @x402/fetch. The provider example imports x402ResourceServer from @x402/core/server and paymentMiddleware from @x402/express; these helpers are not exports of the SubEtha packages. The examples use ESM imports, matching the published packages’ ESM-only runtime contract:

import { x402Client } from "@x402/core/client";
import { wrapFetchWithPayment } from "@x402/fetch";

@subetha/provider — provider-side scheme server and handler

Section titled “@subetha/provider — provider-side scheme server and handler”
Terminal window
npm install @subetha/[email protected] @x402/[email protected] @x402/[email protected] express viem

The published 0.1.0 registry artifact’s documented surface contains four modules. The current source index below is cited for source reconciliation and re-exports five modules at 85fd50ac; its additional history client is listed separately as a source addition and is not asserted as present in the published artifact. (src/index.ts)

export kind description
SubethaChallengeOffer interface the facilitator’s /challenge response: payTo, amount, token, chainId, challengeNonce, expiresAt, helper?, deadline?, fee?
SubethaFacilitatorClient class implements the official FacilitatorClient over HTTP: verify(…), settle(…), getSupported(), plus the SubEtha extension createChallenge(priceBaseUnits)

The facilitator is reached as an external HTTP service — this package includes no facilitator runtime or backend and does not enable launching one.

export kind description
HandlerResult interface what a resource handler returns instead of writing to res: { body, status?, contentType? }
SubethaHandlerResponse interface the structural slice of express.Response the wrapper drives (no express dependency)
subethaHandler(fn) function wraps a return-value handler into an Express-compatible route handler with exactly one response commit; a thrown handler becomes a 500 and the payment is not settled
export kind description
SUBETHA_PLACEHOLDER_PAYTO const fallback payTo for static quote-only route configs; real payment routes must use subethaAccepts
SubethaSchemeServerOptions interface maxCachedOffers? (default 5000), clock?, feePolicy?
SubethaSchemeServer class structurally implements the official SchemeNetworkServer; mints one fresh burn-address offer per unpaid 402 via the facilitator and caches live offers in memory (single-process assumption)
subethaAccepts(schemeServer, { network, price }) function builds a route’s accepts entry whose dynamic payTo mints per 402 and echoes the client’s accepted.payTo on the paying request
export kind description
EXPIRY_SKEW_SECONDS const re-export of the shared clock-skew margin
OfferBinding interface the identity an offer is bound to
SubethaFeePolicy interface the facilitator’s non-secret fee policy as the provider expects it
validateFeePolicy(policy) function fail-fast structural validation of a fee policy
SubethaOfferEntry interface a fully-built cached offer entry
canonicalizePathname(path) function path canonicalization for offer binding
bindingsEqual(a, b) function offer-binding equality
validateChallengeOffer(…) function validates a facilitator challenge offer against the expected binding and fee policy
validateBuiltRequirements(…) function validates the requirements object built from an offer

Current source addition (not asserted as published npm surface)

Section titled “Current source addition (not asserted as published npm surface)”

The merged source also re-exports ProviderHistoryRecord and ProviderHistoryClient from src/history-client.ts. This client binds provider offers to idempotency keys and can acknowledge a resource or accept a finalized claim. It is a source-level addition at 85fd50ac, not a claim that the published @subetha/[email protected] artifact contains it.

const facilitator = new SubethaFacilitatorClient(FACILITATOR_URL);
const scheme = new SubethaSchemeServer(facilitator);
const server = new x402ResourceServer([facilitator]);
server.register("eip155:31337", scheme);
await server.initialize(); // hard-fails unless /supported advertises the kind
app.use(paymentMiddleware({ "/api/*": {
accepts: subethaAccepts(scheme, { network: "eip155:31337", price: "1000" }),
} }, server));

FACILITATOR_URL is the separately operated facilitator HTTP base URL. eip155:31337 is the local development-chain example, not a protocol-wide network restriction. The provider configures its payout address but does not need to hold a signing key for this wiring.

The corresponding x402 imports are:

import { x402ResourceServer } from "@x402/core/server";
import { paymentMiddleware } from "@x402/express";

price is the list price in base units; the quoted amount (with any fee) comes from the facilitator per request. The provider holds no keys except its payout EOA and never touches the chain or the zERC20 SDK.