Prices in your code
Keep prices in your code if you already use x402 middleware or want them under version control. Cryptonly then only settles the payments, and you don’t use the Endpoints tab. Each route sets its own price and payTo, the address that gets paid.
First, follow steps 1 and 2 of the quickstart to add a payout wallet and create an API key. Set PAY_TO to that wallet’s address.
npm install @cryptonly/x402 @x402/core @x402/express @x402/evm expressimport express from 'express';import { CryptonlyFacilitatorClient } from '@cryptonly/x402';import { ExactEvmScheme } from '@x402/evm/exact/server';import { paymentMiddleware, x402ResourceServer } from '@x402/express';
const facilitator = new CryptonlyFacilitatorClient({ apiKey: process.env.CRYPTONLY_API_KEY!,});const server = new x402ResourceServer(facilitator).register( 'eip155:8453', new ExactEvmScheme(),);
const app = express();app.use( paymentMiddleware( { 'GET /v1/weather/:city': { accepts: [ { scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: process.env.PAY_TO! }, ], description: 'Current weather for a city', }, }, server, ),);
app.get('/v1/weather/:city', (req, res) => { res.json({ city: req.params.city, temperatureC: 21 });});app.listen(4021);CryptonlyFacilitatorClient works the same way with @x402/fastify, @x402/hono and @x402/next.
npm install @cryptonly/x402-nestjs @x402/core @x402/evmimport { Controller, Get, Module, Param } from '@nestjs/common';import { X402, X402Module } from '@cryptonly/x402-nestjs';
@Controller('v1/weather')class WeatherController { @X402({ accepts: { scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: process.env.PAY_TO! }, description: 'Current weather for a city', }) @Get(':city') get(@Param('city') city: string) { return { city, temperatureC: 21 }; }}
@Module({ imports: [ X402Module.forRoot({ apiKey: process.env.CRYPTONLY_API_KEY!, isGlobal: true }), ], controllers: [WeatherController],})export class AppModule {}Listen on port 4021 in main.ts. @X402() without arguments takes the price from the Endpoints tab instead; you can mix both in one app. It works on the Express and the Fastify platform.
pip install cryptonly-x402 "x402[fastapi,evm]" fastapi uvicornimport os
from cryptonly_x402 import CryptonlyFacilitatorClientfrom fastapi import FastAPIfrom x402.http import PaymentOption, RouteConfigfrom x402.http.middleware.fastapi import PaymentMiddlewareASGIfrom x402.mechanisms.evm.exact import ExactEvmServerSchemefrom x402.server import x402ResourceServer
facilitator = CryptonlyFacilitatorClient(os.environ["CRYPTONLY_API_KEY"])server = x402ResourceServer(facilitator)server.register("eip155:8453", ExactEvmServerScheme())
routes = { "GET /v1/weather/:city": RouteConfig( accepts=PaymentOption(scheme="exact", price="$0.01", network="eip155:8453", pay_to=os.environ["PAY_TO"]), description="Current weather for a city", ),}
app = FastAPI()app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
@app.get("/v1/weather/{city}")async def weather(city: str): return {"city": city, "temperatureC": 21}Run it with uvicorn main:app --port 4021. For Flask, use CryptonlyFacilitatorClientSync with x402ResourceServerSync.
There is no Cryptonly package for Go. Use the stock HTTP facilitator client and send your key in the x-tenant-api-key header.
go get github.com/x402-foundation/x402/go github.com/gin-gonic/ginpackage main
import ( "context" "os"
"github.com/gin-gonic/gin" x402http "github.com/x402-foundation/x402/go/http" ginmw "github.com/x402-foundation/x402/go/http/gin" evm "github.com/x402-foundation/x402/go/mechanisms/evm/exact/server")
// apiKey sends your Cryptonly API key with every facilitator call.type apiKey string
func (k apiKey) GetAuthHeaders(context.Context) (x402http.AuthHeaders, error) { h := map[string]string{"x-tenant-api-key": string(k)} return x402http.AuthHeaders{Verify: h, Settle: h, Supported: h}, nil}
func main() { facilitator := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ URL: "https://api-merchant.cryptonly.net/x402", AuthProvider: apiKey(os.Getenv("CRYPTONLY_API_KEY")), })
routes := x402http.RoutesConfig{ "GET /v1/weather/:city": { Accepts: x402http.PaymentOptions{ {Scheme: "exact", Price: "$0.01", Network: "eip155:8453", PayTo: os.Getenv("PAY_TO")}, }, Description: "Current weather for a city", }, }
r := gin.Default() r.Use(ginmw.X402Payment(ginmw.Config{ Routes: routes, Facilitator: facilitator, Schemes: []ginmw.SchemeConfig{{Network: "eip155:8453", Server: evm.NewExactEvmScheme()}}, })) r.GET("/v1/weather/:city", func(c *gin.Context) { c.JSON(200, gin.H{"city": c.Param("city"), "temperatureC": 21}) }) r.Run(":4021")}Test it with steps 5 and 6 of the quickstart. After its first payment, the route shows up on the Endpoints tab as Priced in code.
Accept Solana
Section titled “Accept Solana”Register ExactSvmScheme from @x402/svm/exact/server for the Solana network ID and use your Solana wallet as payTo. The scheme gets Cryptonly’s fee payer from the facilitator, so there’s nothing else to configure. In NestJS, install @x402/svm instead: @X402() registers it for a Solana network.
Test in the sandbox
Section titled “Test in the sandbox”Pass sandbox: true (Python: sandbox=True; Go: use https://sandbox-api-merchant.cryptonly.net/x402), change the network to eip155:84532 (Base Sepolia), and use a key and wallet from your sandbox account.