BotPay Facilitator
Welcome to the BotPay Facilitator! This Cloudflare Worker is a self-hosted x402 facilitator that verifies and settles Base mainnet USDC payments directly on-chain. It does not use a third-party facilitator in the verification or settlement path.
API Key Management
Manage API keys and quotas via the Portal UI — register your Botpay facilitator account at /register and visit the Login page at /login to access the API key management dashboard.
The Portal supports adding quota or get new API keys via x402 payments. Users can replenish API key quota by making payments.
Facilitator API
GET /supported
Returns the supported x402 schemes and the public facilitator signer address. Both GET /supported and the legacy GET /facilitator/supported are available.
POST /verify
Verify a payment transaction. The facilitator accepts requests using the canonical x402 v2 shapes (PaymentPayload and PaymentRequirements) via the current @x402/core SDK.
For backward compatibility, POST /facilitator/verify is also available. The standard /verify path is recommended for new integrations.
Response (Verify):
{
"isValid": true,
"invalidReason": null,
"payer": "0xPayerAddress"
}
POST /settle
Settle a verified payment using the x402 payment payload and requirements.
Request Body:
{
"paymentPayload": { ... },
"paymentRequirements": { ... }
}
(Use the same shapes as the /verify request — see the EVM/SVM examples above.)
For backward compatibility, POST /facilitator/settle is also available. The standard /settle path is recommended for new integrations.
Response (Settle):
{
"success": true,
"transaction": "0xTransactionHash",
"network": "base",
"payer": "0xPayerAddress"
}
Notes:
- On failure
successwill befalseanderrorReasonmay indicate the cause (e.g.,insufficient_funds,invalid_payment, etc.). - Both verify and settle operations decrement your API quota by 1.
Authentication
All facilitator API requests require authentication using HMAC signing. You'll need:
- An API Key ID (provided in
X-API-Keyheader) - The corresponding secret key (used for signing, never sent in requests)
HMAC Signing
Requests are signed using HMAC-SHA256. The facilitator implements a header-only signing scheme that uses a timestamp to protect against replay and tampering.
Required headers:
X-API-Key: Your API key IDX-Timestamp: Unix epoch seconds (integer)X-Signature: Hex-encoded HMAC-SHA256 signature
String to sign:
{timestamp}\n{method}\n{path}
Where:
timestampis the value ofX-Timestamp(seconds)methodis the HTTP method in UPPERCASE (e.g.,POST)pathis the request path and query (e.g.,/facilitator/verifyor/facilitator/verify?foo=1)
The existing BotPay client also sends a historical variant with one trailing newline. It remains accepted temporarily so deployed callers continue to work; new clients should use the three-line form above.
HMAC key:
The server stores hashed_secret as hex(SHA-256(secret)). To compute the signature you should:
- Compute
key = SHA256(secret)and use the raw bytes ofkeyas the HMAC key - Compute
signature = hex(HMAC-SHA256(key, stringToSign))
Timestamp window:
The server allows a +/- window controlled by SIGNATURE_WINDOW_SECONDS (default 300 seconds).
Example (Node.js):
const crypto = require('crypto');
function buildSignedHeaders(apiKeyId, secret, method, path = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
const stringToSign = `${timestamp}\n${method.toUpperCase()}\n${path}`;
const key = crypto.createHash('sha256').update(secret).digest(); // raw bytes
const signature = crypto.createHmac('sha256', key).update(stringToSign).digest('hex');
const headers = {
'Content-Type': 'application/json',
'X-API-Key': apiKeyId,
'X-Timestamp': timestamp,
'X-Signature': signature,
};
return headers;
}
// Usage example
const headers = buildSignedHeaders('your-api-key-id', 'your-secret', 'POST', '/facilitator/verify');
const body = JSON.stringify({ paymentPayload: {...}, paymentRequirements: {...} });
fetch('https://facilitator.botpay.network/verify', { method: 'POST', headers, body });
Client Examples
JavaScript Client
// Node client: create an x402 v2 payment, sign it with your EVM signer, then POST to the facilitator
const crypto = require('crypto');
// Use the current @x402/core and @x402/evm client packages to build canonical paymentPayloads.
// Example helper to build HMAC headers matching the facilitator
function buildSignedHeaders(apiKeyId, secret, method, path = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
const stringToSign = `${timestamp}\n${method.toUpperCase()}\n${path}`;
const key = crypto.createHash('sha256').update(secret).digest(); // raw bytes
const signature = crypto.createHmac('sha256', key).update(stringToSign).digest('hex');
const headers = {
'Content-Type': 'application/json',
'X-API-Key': apiKeyId,
'X-Timestamp': timestamp,
'X-Signature': signature,
};
return headers;
}
// Usage example (pseudo-code — replace signer with your viem wallet client or other signer)
async function verifyPayment(apiKeyId, secret, signer, paymentRequirements) {
// Build and sign a canonical x402 v2 paymentPayload with the @x402 client SDK.
const paymentPayload = await createPaymentPayloadWithX402V2(signer, paymentRequirements);
const body = JSON.stringify({ paymentPayload, paymentRequirements });
const headers = buildSignedHeaders(apiKeyId, secret, 'POST', '/facilitator/verify', body);
const res = await fetch('https://facilitator.botpay.network/verify', { method: 'POST', headers, body });
return res.json();
}
Quota Management
- Each API key has a quota limit
- Verify and settle operations consume 1 quota each
- Monitor your remaining quota via the
/api-keysendpoint - Add more quota using the
/add-quotaendpoint
Error Handling
The API returns standard HTTP status codes:
200: Success400: Bad Request401: Unauthorized (invalid signature)403: Forbidden (quota exceeded)500: Internal Server Error
Error responses include a JSON body with success: false and an error message.
Security Best Practices
- Never share your API secret or internal facilitator token
- Use HTTPS for all requests
- Only Base mainnet USDC payments to approved BotPay recipients are accepted
- Monitor your quota usage and Base gas balance
- Rotate API keys regularly
References
- @x402/core — Payment payload/requirements schemas and facilitator helpers: https://www.npmjs.com/package/@x402/core
- @x402/hono — Current Hono middleware for x402 integrations: https://www.npmjs.com/package/@x402/hono
- viem — EVM signing utilities and
verifyTypedData: https://www.npmjs.com/package/viem - @x402/core and @x402/evm — x402 protocol and direct EVM settlement: https://www.npmjs.com/package/@x402/core
- Local implementation:
src/facilitatorCore.js— core verify/settle routes and auth middlewaresrc/internalFacilitatorAuth.js— authorizes the portal's own quota purchase flow
BotPay Facilitator