x402 Agent API Skill
Use this skill to let your AI agent call paid endpoints on https://www.flashcode.live/ with x402.
Quick start for AI agents
- Place this file in your OpenClaw, Codex, or Claude project root.
- Tell your AI agent: "Help me convert this text into a QR code." or "Help me upload this image and return an online URL."
- The agent should follow x402 payment flow automatically.
Install dependencies
npm install @x402/core @x402/evm viem
Required environment variables
EVM_PRIVATE_KEY=0x_your_private_key
API_BASE_URL=https://www.flashcode.live/
Currently available features
- QR code generation
- Image hosting
Available endpoints
Live
GET /api/health- health checkGET /api/v1/capabilities- capability discoveryPOST /api/v1/qrcode/generate- generate QR code image (x402 protected)POST /api/v1/image/upload- upload image and return public URL (x402 protected, max 10MB)
Planned
POST /api/v1/image/colorizePOST /api/v1/image/super-resolutionPOST /api/v1/image/enhancePOST /api/v1/image/smart-redactPOST /api/v1/image/smart-cropPOST /api/v1/image/inpaintPOST /api/v1/image/qrcode/decodePOST /api/v1/image/tagsPOST /api/v1/image/game-scene-detectPOST /api/v1/image/quality-scorePOST /api/v1/vision/face-detectPOST /api/v1/vision/human-detectPOST /api/v1/vision/pet-detectPOST /api/v1/vision/plate-detectPOST /api/v1/image/ocrPOST /api/v1/image/idcard-ocrPOST /api/v1/image/background-removePOST /api/v1/video/object-detectionPOST /api/v1/video/portrait-segmentation
How to call each live endpoint
1) QR code generation
Endpoint: POST /api/v1/qrcode/generate
JSON body:
{
"text": "https://example.com",
"size": 512,
"ecc": "M",
"format": "png",
"margin": 2
}
textis required (1-2048 chars).formatis currentlypngonly.sizerange:128-2048.marginrange:0-16.eccsupports:L | M | Q | H.- Success response contains
result.image_base64andresult.mime_type.
2) Image hosting
Endpoint: POST /api/v1/image/upload
Request type: multipart/form-data
- Use one form-data field named
file. - File type must be
image/*. - File size must be
<= 10MB.
Success response contains result.image_url.
Payment flow
- Call protected endpoint and expect
402 Payment Required. - Parse payment requirements from response headers.
- Sign payment and retry with x402 payment header.
- Read business result (
result.image_urlfor upload).
Example client flow
This example follows the same pattern as scripts/buyer-quickstart-test.ts.
import { x402Client, x402HTTPClient } from "@x402/core/client";
import { ExactEvmScheme, toClientEvmSigner } from "@x402/evm";
import { createPublicClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
const baseUrl =
process.env.X402_API_BASE_URL ??
process.env.API_BASE_URL ??
"https://www.flashcode.live/";
const endpoint = `${baseUrl.replace(/\/$/, "")}/api/v1/qrcode/generate`;
async function main() {
const privateKey = process.env.EVM_PRIVATE_KEY;
if (!privateKey) throw new Error("Missing EVM_PRIVATE_KEY");
if (!privateKey.startsWith("0x")) throw new Error("EVM_PRIVATE_KEY must start with 0x");
const account = privateKeyToAccount(privateKey as `0x${string}`);
const publicClient = createPublicClient({ chain: base, transport: http() });
const signer = toClientEvmSigner(account, publicClient);
const client = new x402Client().register("eip155:*", new ExactEvmScheme(signer));
const httpClient = new x402HTTPClient(client);
const payload = { text: "https://example.com", size: 512, ecc: "M" };
const unpaid = await fetch(endpoint, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(payload),
});
if (unpaid.status !== 402) {
const unpaidBody = await unpaid.text();
throw new Error(`Expected unpaid status 402, got ${unpaid.status}. body=${unpaidBody}`);
}
const paymentRequired = httpClient.getPaymentRequiredResponse(
(name) => unpaid.headers.get(name),
{},
);
const paymentPayload = await httpClient.createPaymentPayload(paymentRequired);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"content-type": "application/json",
...httpClient.encodePaymentSignatureHeader(paymentPayload),
},
body: JSON.stringify(payload),
});
const body = await response.json();
if (!response.ok) throw new Error(`Request failed with status ${response.status}: ${JSON.stringify(body)}`);
console.log(body);
}
void main().catch((error) => {
console.error(error);
process.exit(1);
});
Error handling
402 Payment Required: build payment payload, sign, and retry.500 Internal Server Error: retry with backoff and log request context.
Endpoint-specific error codes
POST /api/v1/image/upload
image_file_required(400):filefield is missing.image_file_empty(400): uploaded file is empty.image_file_too_large(413): image is larger than 10MB.image_mime_not_supported(400): onlyimage/*is supported.invalid_image_request(400): other validation errors.
POST /api/v1/qrcode/generate
invalid_json_body(400): request body is not valid JSON.invalid_request_body(400): body is not a JSON object.qrcode_content_required(400):textis missing or empty.qrcode_content_too_long(400):textexceeds 2048 characters.qrcode_format_not_supported(400): onlypngformat is supported.invalid_qrcode_request(400): other validation errors.