BotPay Facilitator
Welcome to the BotPay Facilitator! This Cloudflare Worker provides a secure API for facilitating payments through the x402 protocol on Ethereum. To start, get API key and secret through our account management portal.
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
POST /verify
Verify a payment transaction. The facilitator accepts requests using the canonical x402 shapes (PaymentPayload and PaymentRequirements) via the x402 Node package implementation — see the x402 package documentation.
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.)
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)
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://your-facilitator.com/facilitator/verify', { method: 'POST', headers, body });
Client Examples
JavaScript Client
// Node client: create an x402 payment (using `x402`), sign it with your EVM signer, then POST to the facilitator
const crypto = require('crypto');
const { createAndSignPayment } = require('x402'); // builds 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 paymentPayload using your signer
const paymentPayload = await createAndSignPayment(signer, {
x402Version: 1,
scheme: 'exact',
network: paymentRequirements.network,
payload: {
// For exact EVM payments, create authorization; createAndSignPayment will sign it
authorization: {
from: '0xSenderAddress',
to: paymentRequirements.payTo,
value: paymentRequirements.maxAmountRequired,
validAfter: '0',
validBefore: `${Math.floor(Date.now() / 1000) + 3600}`,
nonce: '0x...'
}
}
}, paymentRequirements);
const body = JSON.stringify({ paymentPayload, paymentRequirements });
const headers = buildSignedHeaders(apiKeyId, secret, 'POST', '/facilitator/verify', body);
const res = await fetch('https://botpay-facilitator.alexwlex143.workers.dev/facilitator/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 secret key
- Use HTTPS for all requests
- Validate signatures on your end if needed
- Monitor your quota usage
- Rotate API keys regularly
References
- x402 (package) — Payment payload/requirements schemas and facilitator helpers: https://www.npmjs.com/package/x402
- x402-hono — Hono middleware and helpers for x402 integrations: https://www.npmjs.com/package/x402-hono
- viem — EVM signing utilities and
verifyTypedData: https://www.npmjs.com/package/viem - @coinbase/cdp-sdk — Used to generate CDP JWTs for CDP facilitator integration: https://www.npmjs.com/package/@coinbase/cdp-sdk
- Local implementation:
src/facilitatorCore.js— core verify/settle routes and auth middlewaresrc/utils/x402-hono-utils.js— builds CDP JWT headers for verify and settle operations