Developer Documentation
Build with
BagsPay
Add x402 payment gating to any API in 10 lines. Accept USDC on Solana with automatic fee sharing to $BAGS holders.
Quick Start
Protect any Hono route with x402 payments. When a request comes in without payment, the middleware returns HTTP 402. When a valid payment is attached, the request passes through.
import { Hono } from "hono";
import { bagspay } from "@bagspay/server";
const app = new Hono();
// This route now requires 0.01 USDC per request
app.use("/api/premium/*", bagspay({
price: { amount: "0.01", asset: "USDC" },
payTo: "YOUR_SOLANA_WALLET",
facilitatorUrl: "https://facilitator.bagspay.fun",
}));
app.get("/api/premium/data", (c) => {
const payer = c.get("bagspay_payer");
return c.json({ data: "premium content", paidBy: payer });
});
Installation
bun add @bagspay/server # For merchants (accept payments)
bun add @bagspay/client # For agents (make payments)
bun add @bagspay/core # Shared types & utilities
bagspay() Middleware
The server middleware intercepts requests, checks for an X-PAYMENT header, and settles payments via the facilitator.
| Parameter | Type | Description |
| price.amount | string | Price per request in human units (e.g., "0.01") |
| price.asset | string | "USDC", "SOL", or a token mint address |
| price.network | string? | CAIP-2 network ID. Defaults to Solana mainnet |
| payTo | string | Your Solana wallet address (base58) |
| facilitatorUrl | string | URL of the BagsPay facilitator service |
| description | string? | Human-readable description of what's being paid for |
| fees | FeeConfig? | Custom fee split in basis points (default: 97/2/1) |
Subscriptions
Recurring payments with off-chain subscription tracking. The first request charges immediately, subsequent requests check subscription status.
import { bagspaySubscription } from "@bagspay/server";
app.use("/api/pro/*", bagspaySubscription({
plan: "pro-monthly",
name: "Pro Plan",
price: { amount: "5.00", asset: "USDC", interval: "monthly" },
payTo: "YOUR_WALLET",
facilitatorUrl: "https://facilitator.bagspay.fun",
}));
Fee Configuration
Every payment splits fees automatically via Bags Fee Share V2. The default split is 97% merchant / 2% $BAGS vault / 1% treasury. Customize with basis points (10000 = 100%):
app.use("/api/*", bagspay({
price: { amount: "0.05", asset: "USDC" },
payTo: "YOUR_WALLET",
facilitatorUrl: "https://facilitator.bagspay.fun",
fees: {
merchantBps: 9500, // 95%
bagsVaultBps: 400, // 4%
treasuryBps: 100, // 1%
},
}));
BagsPayClient
For AI agents and apps that need to pay for x402-protected resources. The client automatically handles 402 responses, signs payments, and retries.
import { BagsPayClient, keypairAdapter } from "@bagspay/client";
import { Keypair } from "@solana/web3.js";
const client = new BagsPayClient({
wallet: keypairAdapter(Keypair.generate()),
rpcUrl: "https://mainnet.helius-rpc.com/?api-key=YOUR_KEY",
maxAutoPayAmount: "1000000", // Max 1 USDC per request (in base units)
});
// This automatically: gets 402 -> signs payment -> retries -> returns 200
const res = await client.fetch("https://api.example.com/premium/data");
const data = await res.json();
| Parameter | Type | Description |
| wallet | WalletAdapter | Solana wallet for signing payments |
| rpcUrl | string | Solana RPC endpoint |
| maxAutoPayAmount | string? | Spending limit per request (base units) |
| autoPay | boolean? | Auto-pay 402 responses (default: true) |
| maxPaymentRetries | number? | Max payment attempts (default: 1) |
Wallet Adapters
// For AI agents (headless, no UI)
import { keypairAdapter } from "@bagspay/client";
const wallet = keypairAdapter(myKeypair);
// For browser apps (Phantom, Solflare, etc.)
// Implement the WalletAdapter interface:
interface WalletAdapter {
publicKey: string;
signTransaction(tx: Transaction): Promise<Transaction>;
}
Facilitator: POST /settle
Verify a payment and broadcast it to Solana. Called by the server middleware automatically.
POST /settle
Content-Type: application/json
{
"payload": {
"x402Version": 1,
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"payload": {
"transaction": "<base64-encoded-signed-tx>",
"payer": "<base58-wallet-address>"
}
},
"requirement": {
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"maxAmountRequired": "10000",
"payTo": "<merchant-wallet>",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"maxTimeoutSeconds": 60
}
}
POST /verify
Validate a payment without broadcasting. Returns { valid: true/false }.
GET /supported
List supported schemes and networks.
{ "schemes": ["exact"], "networks": ["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"] }
GET /health
Health check with Solana RPC and database latency.
{ "status": "healthy", "checks": { "solanaRpc": { "ok": true, "latencyMs": 45 }, "database": { "ok": true, "latencyMs": 1 } } }
Register an Agent on the Marketplace
List your AI agent so others can pay to use it. Every call generates $BAGS fees for holders.
curl -X POST https://marketplace.bagspay.fun/agents/register \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ADMIN_KEY" \
-d '{
"id": "my-agent",
"name": "My Agent",
"description": "Does something useful",
"pricePerCall": "0.01",
"monthlyPrice": "5.00",
"endpoint": "https://my-agent.example.com/api"
}'
| Field | Required | Description |
| id | Yes | Lowercase alphanumeric with hyphens, max 64 chars |
| name | Yes | Display name for the agent |
| description | Yes | What the agent does |
| pricePerCall | Yes | USDC price per call (e.g., "0.01") |
| monthlyPrice | No | Monthly subscription price in USDC |
| endpoint | No | HTTPS URL your agent listens on |
BagsPay - x402 Payment Infrastructure for Solana. Built for the Bags Hackathon.