Skip to main content
Extensions are the composable layer on top of x402’s core payment protocol. They let resource servers, facilitators, and clients add optional capabilities — discovery, authentication, receipts, gas sponsoring — without modifying the core payment flow.

How Extensions Work

x402 has two extension points that serve different roles in the payment flow:

Resource Server Extensions

These run on the resource server (the service accepting payments) and hook into the HTTP payment lifecycle. A ResourceServerExtension can intervene at four points:
  1. Declaration (enrichDeclaration) — Called at route registration time. The extension can modify or narrow the route’s extension declaration based on transport context (e.g., Bazaar narrows the HTTP method).
  2. 402 Response (enrichPaymentRequiredResponse) — Called when the server returns 402 Payment Required. The extension can add data to the response (e.g., signed offers, discovery metadata).
  3. Settlement Response (enrichSettlementResponse) — Called after successful payment. The extension can add data to the PAYMENT-RESPONSE header (e.g., signed receipts, payment identifiers).
  4. Verify/settle lifecycle hooks (hooks) — Scoped verify and settle hooks that run only when the extension is declared on the route. These follow the same pattern as the server-level hooks (onBeforeVerify, onAfterVerify, onVerifyFailure, onBeforeSettle, onAfterSettle, onSettleFailure) but receive the extension’s declaration as a first argument.
All four points are optional. Most extensions use one or two — not all.

Facilitator Extensions

These run on the facilitator (the service that verifies and settles payments on behalf of the resource server). A FacilitatorExtension provides a key and is stored for use by mechanism implementations during verification and settlement. Gas sponsoring extensions are the primary example — they inject batch signing capabilities into the settlement flow so the facilitator can sponsor gas on behalf of the payer.

Registering an Extension (Server)

Extensions implement the ResourceServerExtension interface and are registered via registerExtension:
Each extension has a unique key that identifies it in route declarations and response payloads.

The ResourceServerExtension Interface

Declaring Extensions on Routes

Extensions are declared per-route in the payment middleware configuration. Each extension’s declaration goes under extensions keyed by the extension’s key:
If an extension is declared on a route but not registered on the server, it is silently ignored.

Which Hooks Do Extensions Use?

Not all extensions use the same hooks. Here’s how the built-in extensions map to the extension points: Bazaar is unique in that it spans both sides: the resource server extension enriches declarations, while the facilitator component handles discovery cataloging and validation. Sign-In-With-X manages its own session lifecycle outside the standard hooks.

Available Extensions

Building a Custom Extension

To create your own extension:
  1. Define the extension object implementing ResourceServerExtension
  2. Choose a unique key — this identifies your extension in route declarations and response payloads
  3. Implement the hooks you needenrichDeclaration, enrichPaymentRequiredResponse, enrichSettlementResponse, and/or hooks
  4. Create a declare function — a helper that returns the route-level configuration for your extension
  5. Register it on the x402ResourceServer via registerExtension
  6. Submit a pull request to x402-foundation/x402 — extensions must be reviewed and approved by the x402 maintainers before they are included in the SDK
Here’s a minimal example:
The data returned from enrichPaymentRequiredResponse and enrichSettlementResponse is included in the response under extensions["my-extension"]. The hooks callbacks run as part of the server’s verify/settle lifecycle but only when the extension is active on the route.

Further Reading