API Documentation
CheckPoint is a self-hosted x402 facilitator for Base. Integrate payments in 5 minutes.
Quickstart
Install the SDK (optional)
npm install @x402-checkpoint/sdkimport { CheckPointClient } from '@x402-checkpoint/sdk';
const client = new CheckPointClient();
const health = await client.health();Server: Return 402 with payment requirements
// When client requests paid resource
res.status(402).json({
x402Version: 2,
payTo: "0xYourWallet",
amount: "10000", // 0.01 USDC (6 decimals)
network: "eip155:8453", // Base Mainnet
asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
facilitator: "https://checkpoint-pied.vercel.app"
});Client: Sign EIP-3009 authorization
import { signTypedData } from 'viem/accounts';
const authorization = {
from: clientWallet,
to: payTo,
value: BigInt(amount),
validAfter: 0n,
validBefore: BigInt(Math.floor(Date.now() / 1000) + 3600),
nonce: `0x${crypto.randomBytes(32).toString('hex')}`
};
const signature = await wallet.signTypedData({
domain: { name: 'USDC', version: '2', chainId: 8453, verifyingContract: asset },
types: { TransferWithAuthorization: [...] },
primaryType: 'TransferWithAuthorization',
message: authorization
});Server: Verify and settle
// Verify payment
const verifyRes = await fetch('https://checkpoint-pied.vercel.app/api/v2/x402/verify', {
method: 'POST',
body: JSON.stringify({ paymentPayload, paymentRequirements })
});
const { valid } = await verifyRes.json();
if (valid) {
// Settle payment (USDC transfers client → you)
await fetch('https://checkpoint-pied.vercel.app/api/v2/x402/settle', {
method: 'POST',
body: JSON.stringify({ paymentPayload, paymentRequirements })
});
// Serve resource
res.json({ data: "your content" });
}◎ Solana Integration
CheckPoint supports Solana via the SPL Token delegate pattern. Network IDs: solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (Mainnet) or solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 (Devnet)
One-Time: Setup Delegate Approval
Payers must approve CheckPoint as a delegate for their USDC tokens.
import { fetchDelegateSetup, SOLANA_NETWORKS } from '@x402-checkpoint/sdk';
const setup = await fetchDelegateSetup({
facilitatorUrl: 'https://checkpoint-pied.vercel.app',
payer: wallet.publicKey.toBase58(),
network: SOLANA_NETWORKS.DEVNET,
amount: '1000000000', // 1000 USDC
});
// Build and submit approve transaction
const transaction = new Transaction().add(
new TransactionInstruction({
programId: new PublicKey(setup.instruction.programId),
keys: setup.instruction.keys.map(k => ({
pubkey: new PublicKey(k.pubkey),
isSigner: k.isSigner,
isWritable: k.isWritable,
})),
data: Buffer.from(setup.instruction.data, 'base64'),
})
);
await wallet.sendTransaction(transaction, connection);Create and Sign Payment Authorization
import {
createSolanaAuthorization,
signSolanaPayment,
createSolanaPaymentPayload,
SOLANA_NETWORKS,
} from '@x402-checkpoint/sdk';
// Create authorization
const authorization = createSolanaAuthorization({
from: wallet.publicKey.toBase58(),
to: 'MerchantWalletPubkey',
amount: '1000000', // 1 USDC
timeoutSeconds: 3600,
});
// Sign with wallet adapter
const signature = await signSolanaPayment(
authorization,
async (msg) => await wallet.signMessage(msg)
);
// Create payment payload
const paymentPayload = createSolanaPaymentPayload({
authorization,
signature,
network: SOLANA_NETWORKS.DEVNET,
});Verify and Settle
const paymentRequirements = {
scheme: 'exact',
network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
amount: '1000000',
asset: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', // Devnet USDC
payTo: 'MerchantWalletPubkey',
maxTimeoutSeconds: 3600,
};
// Verify
const verifyRes = await fetch('https://checkpoint-pied.vercel.app/api/v2/x402/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ paymentPayload, paymentRequirements }),
});
const { valid, payer, amount } = await verifyRes.json();
if (valid) {
// Settle - USDC transfers from payer to merchant
const settleRes = await fetch('https://checkpoint-pied.vercel.app/api/v2/x402/settle', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ paymentPayload, paymentRequirements }),
});
const { success, txHash } = await settleRes.json();
console.log('Settlement TX:', txHash);
}Solana Network Constants
// Network IDs (CAIP-2)
const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';
const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';
// USDC Mint Addresses
const MAINNET_USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const DEVNET_USDC = '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU';Required Dependencies
npm install @x402-checkpoint/sdk @solana/web3.js @solana/wallet-adapter-react @solana/wallet-adapter-react-ui @solana/wallet-adapter-walletsTest Tokens (Devnet)
Before testing, get these tokens:
- SOL (for fees): faucet.solana.com
- USDC (for payments): spl-token-faucet.com
Delegate Approval
Users must approve CheckPoint as a delegate before payments can be settled. Use our delegate approval page or integrate the component into your app.
Authentication
Core payment endpoints (verify/settle) require no authentication. Admin endpoints require an API key or master key.
# Create API key (requires FACILITATOR_MASTER_KEY)
curl -X POST https://checkpoint-pied.vercel.app/api/keys \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"ownerId": "merchant1", "scopes": ["payments:read"]}'Payments
/api/v2/x402/verifyVerify a signed payment before serving content. No auth required.
cURL
curl -X POST https://checkpoint-pied.vercel.app/api/v2/x402/verify \
-H "Content-Type: application/json" \
-d '{"paymentPayload": {...}, "paymentRequirements": {...}}'Request Body
{
"paymentPayload": {
"x402Version": 2,
"resource": {
"url": "https://api.example.com/premium/data",
"description": "Premium API endpoint",
"mimeType": "application/json"
},
"accepted": {
"scheme": "exact",
"network": "eip155:8453",
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"maxTimeoutSeconds": 60
},
"payload": {
"signature": "0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d41b",
"authorization": {
"from": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD00",
"to": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"value": "10000",
"validAfter": "0",
"validBefore": "1999999999",
"nonce": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "eip155:8453",
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"maxTimeoutSeconds": 60
}
}Response
{
"valid": true,
"payer": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD00",
"payee": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"amount": "10000",
"nonce": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"simulationPassed": true
}/api/v2/x402/settleExecute on-chain USDC transfer. Requires prior verification.
cURL
curl -X POST https://checkpoint-pied.vercel.app/api/v2/x402/settle \
-H "Content-Type: application/json" \
-d '{"paymentPayload": {...}, "paymentRequirements": {...}}'Response
{
"success": true,
"network": "eip155:8453",
"txHash": "0x...",
"blockNumber": 12345678,
"gasUsed": "85000"
}/api/paymentsQuery payment history. Requires payments:read scope.
cURL
curl https://checkpoint-pied.vercel.app/api/payments \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"payments": [
{
"id": "pay_...",
"payer": "0x...",
"payee": "0x...",
"amount": "10000",
"status": "settled",
"txHash": "0x...",
"createdAt": "2024-01-01T00:00:00Z"
}
],
"total": 1
}Discovery
/api/discoveryBrowse registered services. Public, no auth required.
cURL
curl https://checkpoint-pied.vercel.app/api/discoveryResponse
{
"services": [
{
"id": "svc_...",
"name": "AI Analysis API",
"description": "GPT-powered analysis",
"url": "https://api.example.com",
"pricing": { "model": "per_request", "amount": "10000" },
"categories": ["AI", "Analysis"]
}
]
}/api/discoveryRegister your service. Requires discovery:write scope.
cURL
curl -X POST https://checkpoint-pied.vercel.app/api/discovery \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "My AI Service", ...}'Request Body
{
"name": "My AI Service",
"description": "Description of service",
"url": "https://api.myservice.com",
"paymentEndpoint": "/v1/analyze",
"networks": ["eip155:8453"],
"pricing": {
"model": "per_request",
"amount": "10000",
"currency": "USDC"
},
"categories": ["AI"]
}Response
{
"id": "svc_...",
"name": "My AI Service",
"status": "active"
}Admin
/api/keysCreate API key. Requires master key.
cURL
curl -X POST https://checkpoint-pied.vercel.app/api/keys \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"ownerId": "merchant1", "scopes": ["payments:read"]}'Request Body
{
"ownerId": "merchant1",
"scopes": ["payments:read", "webhooks:write"],
"label": "Production Key"
}Response
{
"id": "key_...",
"key": "cp_live_...", // Only shown once!
"prefix": "cp_live_abc",
"scopes": ["payments:read", "webhooks:write"]
}/api/webhooksConfigure webhook. Requires webhooks:write scope.
cURL
curl -X POST https://checkpoint-pied.vercel.app/api/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://...", "events": ["payment.settled"]}'Request Body
{
"url": "https://your-server.com/webhook",
"events": ["payment.verified", "payment.settled", "payment.failed"]
}Response
{
"id": "wh_...",
"url": "https://your-server.com/webhook",
"secret": "whsec_...", // For HMAC verification
"events": ["payment.verified", "payment.settled"]
}/api/healthHealth check. Public, no auth required.
cURL
curl https://checkpoint-pied.vercel.app/api/healthResponse
{
"status": "healthy",
"version": "1.0.0",
"redis": { "connected": true },
"networks": [
{ "id": "eip155:8453", "name": "Base", "status": "connected" }
]
}Error Codes
All possible error codes returned by CheckPoint API endpoints.
Verification Errors
| Code | Description | Solution |
|---|---|---|
INVALID_SIGNATURE | EIP-712 signature verification failed | Check signature creation matches USDC domain |
AUTHORIZATION_EXPIRED | validBefore timestamp passed | Re-sign with new validBefore |
AUTHORIZATION_NOT_YET_VALID | validAfter not yet reached | Wait or use validAfter: 0 |
INSUFFICIENT_BALANCE | Payer lacks USDC | Fund payer wallet |
AMOUNT_MISMATCH | Authorization amount wrong | Match amount to requirements |
PAYEE_MISMATCH | Authorization payee wrong | Match payee to requirements |
NONCE_ALREADY_USED | Replay attack prevented | Generate new random nonce |
SIMULATION_FAILED | On-chain simulation failed | Check contract state |
Settlement Errors
| Code | Description | Solution |
|---|---|---|
VERIFICATION_REQUIRED | Must verify first | Call /verify before /settle |
NONCE_ALREADY_SETTLED | Payment already processed | Check receipt by txHash |
SETTLEMENT_IN_PROGRESS | Another attempt running | Wait and check status |
TRANSACTION_FAILED | TX submission failed | Retry with new nonce |
TRANSACTION_REVERTED | TX reverted on-chain | Check balance/allowance |
INSUFFICIENT_GAS | Facilitator needs ETH | Fund facilitator wallet |
Error Handling
import { CheckPointClient, CheckPointError } from '@x402-checkpoint/sdk';
const checkpoint = new CheckPointClient();
try {
const result = await checkpoint.verify({
paymentPayload: { ... },
paymentRequirements: { ... }
});
} catch (error) {
if (error instanceof CheckPointError) {
switch (error.code) {
case 'INSUFFICIENT_BALANCE':
console.log('Payer needs more USDC');
break;
case 'AUTHORIZATION_EXPIRED':
console.log('Need to re-sign with new validBefore');
break;
case 'NONCE_ALREADY_USED':
console.log('Generate new nonce and re-sign');
break;
default:
console.log('Error:', error.message);
}
// Check retryability
if (error.isRetryable) {
// 5xx errors or network issues - can retry
}
}
}Retry Logic
The SDK automatically retries on network errors and 5xx responses with exponential backoff:
const checkpoint = new CheckPointClient({
retry: {
maxRetries: 3, // Maximum attempts
baseDelay: 1000, // Initial delay (ms)
maxDelay: 10000 // Max delay cap (ms)
}
});