GoPlausible has built the reference implementation, packages, documentation and example codes for Algorand (AVM) X402 integration available as FOSS and also contributed to the Algorand Foundation PR to Coinbase's x402 protocol repo: Coinbase x402 PR #361 which has been merged to Coinbase x402 repository and is available in the main Coinbase 402 repository.
By collaboration between Algorand Foundation and GoPlausible, The x402 protocol has been extended to support Algorand Virtual Machine (AVM), enabling payment verification and settlement on Algorand networks (both mainnet and testnet). This implementation follows the Algorand exact payment scheme and also the implementation patterns established for EVM and SVM networks for 100% alignment, providing a consistent developer experience across all supported blockchains.
Key features of the Algorand implementation:
- Native Protocol Features: Uses Algorand's native transaction capabilities for flexible, secure and efficient payments.
- Fee Abstraction: Supports fee delegation through atomic transaction groups
- Asset Support: Handles both ALGO and Algorand Standard Assets (ASAs)
- Fast Finality: Benefits from Algorand's sub-5 second transaction finality
- Wallet Support: Integrates with Algorand wallets via
@txnlab/use-wallet
The Algorand implementation of x402 utilizes several unique features of the Algorand blockchain:
The implementation allows for composability of transactions within the payment group, enabling more complex interactions such as multi-step payments, conditional payments, or integrating with other smart contracts on Algorand.
The paymentGroup can include additional transactions beyond the payment and fee transactions, and the paymentIndex field specifies which transaction in the group is the actual payment transaction. This flexibility allows developers to create more sophisticated payment flows while still adhering to the x402 protocol.
Atomic transaction groups enable fee abstraction as well, allowing a third-party fee payer to cover transaction fees on behalf of the resource requester. This is achieved by grouping the payment transaction with a fee transaction from the fee payer.
This transaction is not signed by the client but is included in the paymentGroup and the protocol ensures that the fee transaction covers the fees for both transactions in the group. This allows for a seamless user experience where the client can make payments without needing to hold ALGO for fees, while still ensuring that the resource server receives the required payment.
The implementation supports both native ALGO payments and transfers of Algorand Standard Assets (ASAs) e.g. USDC, with special handling for:
- ASA opt-in verification
- Asset ID validation
- Decimal place conversions on asset units and amounts
Algorand has a dedicated facilitator that handles payment verification and settlement for the x402 protocol on Algorand MAINNET and TESTNET:
- Facilitator Address: x402-avm-facilitator
- Supported Networks: Algorand Mainnet and Testnet, Solana Mainnet and Devnet, Base ETH and Sepolia. Check live here Algorand x402 supported networks
- Facilitator API docs: Algorand x402 Facilitator OpenAPI docs
- x402 V2 Core Package @x402/core
- x402 V2 AVM (Algorand) Mechanism @x402/avm
- x402 V2 Extensions @x402/extensions
- x402 V2 Paywall UI @x402/paywall
- x402 V2 Express Middleware @x402/express
- x402 V2 Hono Middleware @x402/hono
- x402 V2 Next.js Middleware @x402/next
- x402 V2 Fetch Client @x402/fetch
- x402 V2 Axios Client @x402/axios
-
x402 V2 Python SDK x402-avm
Extras packages for Python SDK: [all] , [clients] , [evm] , [extensions] , [fastapi] , [flask] , [httpx] , [mechanisms] , [requests] , [servers] , [svm]
- x402 V2 Core Package Examples x402-avm-core-examples
- x402 V2 AVM (Algorand) Mechanism Examples x402-avm-avm-examples
- x402 V2 Extensions Examples x402-avm-extensions-examples
- x402 V2 Paywall UI Examples x402-avm-paywall-examples
- x402 V2 Express Middleware Examples x402-avm-express-examples
- x402 V2 Hono Middleware Examples x402-avm-hono-examples
- x402 V2 Next.js Middleware Examples x402-avm-next-examples
- x402 V2 Fetch Client Examples x402-avm-fetch-examples
- x402 V2 Axios Client Examples x402-avm-axios-examples
- x402 V2 AVM (Algorand) Mechanism Examples (Python) x402-avm-avm-examples-python
- x402 V2 Extensions Examples (Python) x402-avm-extensions-examples-python
- x402 V2 FastAPI Middleware Examples (Python) x402-avm-fastapi-examples-python
- x402 V2 Flask Middleware Examples (Python) x402-avm-flask-examples-python
- x402 V2 HTTPX Client Examples (Python) x402-avm-httpx-examples-python
- x402 V2 Requests Client Examples (Python) x402-avm-requests-examples-python
Client → Resource Server → Facilitator → Algorand Network
│ │ │ │
│ 1. GET │ │ │
│─────────>│ │ │
│ 2. 402 │ │ │
│<─────────│ │ │
│ 3. Build │ │ │
│ payload│ │ │
│ 4. GET + │ │ │
│ X-PAYMENT│ │ │
│─────────>│ 5. verify() │ │
│ │─────────────────>│ 6. simulate │
│ │ │───────────────>│
│ │ │<───────────────│
│ │<─────────────────│ │
│ │ 7. settle() │ │
│ │─────────────────>│ 8. sign + send │
│ │ │───────────────>│
│ │ │<───────────────│
│ │<─────────────────│ 9. txId │
│ 10. 200 │ │ │
│<─────────│ │ │
-
Client requests a protected resource and receives a
402 Payment Requiredresponse containingpaymentRequirements(scheme, network, amount, asset, payTo, extra) -
Client creates an atomic transaction group based on
paymentRequirements:Without fee abstraction (no
feePayerinextra):- Single ASA transfer transaction (
axfer) with:- Sender: client's Algorand address
- Receiver:
paymentRequirements.payTo - Amount:
paymentRequirements.amount(atomic units) - Asset Index:
paymentRequirements.asset(ASA ID) - Fee: minimum fee (1000 microAlgos)
- Note:
"x402-payment-v2"(bytes)
With fee abstraction (
feePayerinextra):- Transaction [0] — Fee Payer (unsigned, for facilitator to sign):
- Type:
pay(payment) - Sender:
feePayeraddress - Receiver:
feePayer(self-payment) - Amount:
0 - Fee:
minFee × 2(pooled fee covering both transactions) - FlatFee:
true - Note:
"x402-fee-payer"(bytes)
- Type:
- Transaction [1] — ASA Transfer (signed by client):
- Type:
axfer(asset transfer) - Sender: client's address
- Receiver:
paymentRequirements.payTo - Amount:
paymentRequirements.amount - Asset Index:
paymentRequirements.asset - Fee:
0(fee payer covers) - FlatFee:
true - Note:
"x402-payment-v2"(bytes)
- Type:
- Atomic group ID is assigned to both transactions
- Single ASA transfer transaction (
-
Client signs only its own transactions (ASA transfer), leaves fee payer transaction unsigned. Encodes all transactions as base64 msgpack strings in
paymentGrouparray. -
Client sends the request with
X-PAYMENTheader containing the payload:{ "x402Version": 2, "scheme": "exact", "network": "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "payload": { "paymentGroup": [ "<base64-fee-payer-txn>", "<base64-signed-asa-transfer>" ], "paymentIndex": 1 } } -
Resource Server forwards the payment to the Facilitator for verification.
-
Facilitator runs
verify():- Validates payload format (
paymentGrouparray,paymentIndexbounds) - Validates group size ≤ 16 transactions
- Decodes all transactions (signed and unsigned)
- Only allows unsigned transactions from facilitator-managed addresses
- Verifies group ID consistency across all transactions
- Security checks on all transactions:
- No
keyreg(key registration) transactions - No
rekeyTo(unless balanced sandwich pattern: A→B then B→A) - No
closeRemainderToorassetCloseTofields (prevents account draining)
- No
- Verifies payment transaction at
paymentIndex:- Type must be
axfer(asset transfer) - Asset ID matches
requirements.asset - Receiver matches
requirements.payTo - Amount matches
requirements.amount - Transaction is signed
- Type must be
- Verifies fee payer transaction (if present):
- Sender is in facilitator's managed addresses
- Type is
pay, amount is0, nocloseRemainderTo, norekeyTo - Fee ≤
MAX_REASONABLE_FEE(10 Algo / 10,000,000 microAlgos)
- Signs fee payer transaction and simulates the full group on-chain
- Returns
VerifyResponse { isValid, invalidReason? }
- Validates payload format (
-
Facilitator runs
settle():- Re-verifies the payment
- Signs all facilitator-managed transactions (fee payer)
- Submits the complete signed group to the Algorand network
- Extracts the payment transaction ID
- Returns
SettleResponse { success, transaction (txId), network }
-
Resource Server grants access to the protected resource
- Instant Finality: Algorand transactions are final in ~3.3 seconds — no reorgs, no rollbacks
- Atomic Groups: Up to 16 transactions execute all-or-nothing (no partial failures)
- Fee Pooling: One transaction in a group can pay fees for all others
- Composability: Additional transactions (smart contract calls, opt-ins) can be added to the
paymentGroupalongside the payment
x402 V2 uses CAIP-2 identifiers — the genesis hash uniquely identifies each Algorand network:
| Network | CAIP-2 Identifier |
|---|---|
| Algorand Mainnet | algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8= |
| Algorand Testnet | algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI= |
V1 legacy identifiers (algorand-mainnet, algorand-testnet) are still supported via automatic mapping.
// TypeScript
type PaymentRequirements = {
scheme: string; // "exact"
network: Network; // CAIP-2 identifier
asset: string; // ASA ID as string (e.g., "10458941" for USDC testnet)
amount: string; // Amount in atomic units (smallest unit)
payTo: string; // Recipient address (58-char Algorand address)
maxTimeoutSeconds: number; // Payment validity window
extra: Record<string, unknown>; // AVM-specific: feePayer, decimals
};# Python
class PaymentRequirements(BaseX402Model):
scheme: str # "exact"
network: Network # CAIP-2 identifier
asset: str # ASA ID as string
amount: str # Atomic units (smallest unit)
pay_to: str # Recipient address
max_timeout_seconds: int # Validity window
extra: dict[str, Any] # feePayer, decimals| Key | Type | Description | Source |
|---|---|---|---|
feePayer |
string |
Fee payer address for gasless payments | Facilitator's getExtra() |
decimals |
number |
Asset decimals (e.g., 6 for USDC) | Server enhancement |
const paymentRequirements = {
scheme: "exact",
network: "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
amount: "10000", // 0.01 USDC (6 decimal places)
asset: "10458941", // USDC ASA ID on Algorand Testnet
payTo: "PAYEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
maxTimeoutSeconds: 60,
extra: {
decimals: 6,
feePayer: "PAYERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
},
};// TypeScript
interface ExactAvmPayloadV2 {
/** Array of base64-encoded msgpack transactions forming an atomic group */
paymentGroup: string[];
/** Zero-based index of the payment transaction within paymentGroup */
paymentIndex: number;
}# Python
@dataclass
class ExactAvmPayload:
payment_group: list[str] = field(default_factory=list)
payment_index: int = 0{
"x402Version": 2,
"scheme": "exact",
"network": "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"payload": {
"paymentGroup": ["iqNhbXQAo2ZlZc0H0KJm...==", "iqNhbXTOAAAnEKRhcmN2..."],
"paymentIndex": 1
}
}| Constant | Value | Description |
|---|---|---|
| USDC Mainnet ASA ID | 31566704 |
USDC on Algorand Mainnet |
| USDC Testnet ASA ID | 10458941 |
USDC on Algorand Testnet |
| USDC Decimals | 6 |
Decimal places for USDC |
| Min Transaction Fee | 1000 microAlgos |
Minimum fee per transaction |
| Max Atomic Group Size | 16 |
Maximum transactions in a group |
| Max Reasonable Fee | 10,000,000 microAlgos (10 Algo) |
Safety cap for fee payer transactions |
The facilitator verifies and settles payments. It needs a private key to sign fee payer transactions.
Online Facilitator: You can use the public GoPlausible facilitator at
https://facilitator.goplausible.xyzinstead of running your own.
# Server port (default: 4022)
PORT=4022
# AVM facilitator private key (Base64-encoded, 64 bytes: 32-byte seed + 32-byte pubkey)
AVM_PRIVATE_KEY=<your-base64-private-key>
# Algod endpoint (optional — defaults to AlgoNode public testnet)
ALGOD_SERVER=https://testnet-api.algonode.cloud
ALGOD_TOKEN=# Server port (default: 4022)
PORT=4022
# AVM facilitator private key (Base64-encoded, 64 bytes: 32-byte seed + 32-byte pubkey)
AVM_PRIVATE_KEY=<your-base64-private-key>
# Algod endpoint (optional — defaults to AlgoNode public testnet)
ALGOD_SERVER=https://testnet-api.algonode.cloud
ALGOD_TOKEN=The Next.js reference site bundles the facilitator as an API route (/facilitator). It uses different env var names with FACILITATOR_ prefix.
# Facilitator URL (both server-side and client-side)
NEXT_PUBLIC_FACILITATOR_URL=http://localhost:3000/facilitator
FACILITATOR_URL=http://localhost:3000/facilitator
# Or use the online facilitator:
# NEXT_PUBLIC_FACILITATOR_URL=https://facilitator.goplausible.xyz
# FACILITATOR_URL=https://facilitator.goplausible.xyz
# AVM facilitator private key (Base64-encoded, 64 bytes: 32-byte seed + 32-byte pubkey)
FACILITATOR_AVM_PRIVATE_KEY=<your-base64-private-key>
# AVM payee address (58-character Algorand address)
RESOURCE_AVM_ADDRESS=YOUR_ALGORAND_ADDRESS_HEREThe resource server protects endpoints and requires payment via x402.
# AVM payee address (receives payments)
AVM_ADDRESS=YOUR_ALGORAND_ADDRESS_HERE
# Facilitator URL for payment verification
FACILITATOR_URL=http://localhost:4022
# Or use the online facilitator:
# FACILITATOR_URL=https://facilitator.goplausible.xyz# AVM payee address (receives payments)
AVM_ADDRESS=YOUR_ALGORAND_ADDRESS_HERE
# Facilitator URL for payment verification
FACILITATOR_URL=http://localhost:4022
# Or use the online facilitator:
# FACILITATOR_URL=https://facilitator.goplausible.xyzThe client makes payments to access protected resources.
# AVM client private key (Base64-encoded, 64 bytes)
AVM_PRIVATE_KEY=<your-base64-private-key>
# Protected resource server
RESOURCE_SERVER_URL=http://localhost:4021
ENDPOINT_PATH=/weather# AVM client private key (Base64-encoded, 64 bytes)
AVM_PRIVATE_KEY=<your-base64-private-key>
# Protected resource server
RESOURCE_SERVER_URL=http://localhost:4021
ENDPOINT_PATH=/weatherThe AVM_PRIVATE_KEY / FACILITATOR_AVM_PRIVATE_KEY is a Base64-encoded 64-byte key:
- First 32 bytes: Ed25519 seed (private key)
- Last 32 bytes: Ed25519 public key
- Address is derived from the public key:
encode_address(secret_key[32:])
The SDK uses AlgoNode public endpoints by default. Override with environment variables:
# Custom Algod endpoints (optional — fallback to AlgoNode)
ALGOD_MAINNET_URL=https://mainnet-api.algonode.cloud # default
ALGOD_TESTNET_URL=https://testnet-api.algonode.cloud # default
# Python SDK also supports custom Indexer endpoints
INDEXER_MAINNET_URL=https://mainnet-idx.algonode.cloud # default
INDEXER_TESTNET_URL=https://testnet-idx.algonode.cloud # defaultBreaking Change:
algosdkhas been removed as a direct dependency. The AVM packages now use@algorandfoundation/algokit-utils(v10 alpha) internally. If you were previously installingalgosdkalongside@x402/avm, remove it from your install command and uninstall it from your project.
# Core packages
npm install @x402/core @x402/avm
# Server middleware (choose one)
npm install @x402/express # Express.js
npm install @x402/hono # Hono
npm install @x402/next # Next.js
# Client packages (choose one)
npm install @x402/fetch # Fetch API
npm install @x402/axios # Axios
# Paywall UI (optional)
npm install @x402/paywall
# Wallet integration (for browser clients)
npm install @txnlab/use-wallet# Minimal AVM support
pip install x402-avm[avm]
# Server frameworks (choose one)
pip install x402-avm[avm,fastapi]
pip install x402-avm[avm,flask]
# HTTP clients (choose one)
pip install x402-avm[avm,httpx]
pip install x402-avm[avm,requests]
# Full installation (all mechanisms + all extras)
pip install x402-avm[all]- x402 Core Package
- x402-express Package
- x402-hono Package
- x402-next Package
- x402-fetch Package
- x402-axios Package
This guide provides comprehensive documentation and examples for using the x402 protocol with Algorand (AVM) across various packages.