x402 vs Sume's 402: a prepaid-balance error, not a payment prompt
Sume returns HTTP 402 with the code insufficient_credits when the balance is too low. The fix is adding funds, not sending a payment header.

A 402 from Sume means the workspace balance is too low, not that a per-request payment is due. The body carries the code insufficient_credits. Sume documents no payment-method header and no x402 flow; you fix it by adding funds or lowering the request cost, then retrying.
The x402 side is from Cloudflare's 2026-09-30 AI Gateway changelog; Sume's side is from Errors and rate limits, both read 2026-09-30.
What does Cloudflare's x402 flow do?
The changelog says AI Gateway Machine Payments, in beta, lets clients use the x402 protocol to pay for eligible inference requests from a stablecoin wallet instead of keeping a prepaid credit balance. It applies to the /ai/run endpoint with select open models, and you request it with a Cloudflare API token plus a Payment-Method: x402 header. That header is Cloudflare-specific.
How do the two 402s differ?
| Question | Cloudflare Machine Payments | Sume |
|---|---|---|
| What pays | Stablecoin wallet via x402 | Prepaid balance |
| Trigger | Client sends Payment-Method: x402 | Balance not sufficient for the generation |
| Error code | Not covered here | insufficient_credits |
| Auth | Cloudflare API token | x-api-key from the SDK, or Bearer |
| Fix | Not covered here | Add funds or lower request cost |
How should my client handle a Sume 402?
Branch on the error code, not the status alone. The docs define 402 insufficient_credits as a balance that is not sufficient for the requested generation, and list quota job errors with the next action "Add funds or lower request cost". Add funds or lower the cost rather than retrying blindly: stop the loop, surface the message and the request_id, and resume after the balance changes.
const res = await fetch("https://api.sume.com/v1/image-1.0/generate", {
method: "POST",
headers: {
"x-api-key": process.env.SUME_API_KEY ?? "",
"Content-Type": "application/json",
"Idempotency-Key": "hero-shot-2026-09-30-001",
},
body: JSON.stringify({ prompt: "Product hero shot", mode: "async" }),
});
const body = await res.json();
if (res.status === 402 && body.error?.code === "insufficient_credits") {
console.error("Add funds, then resubmit with the same key:", body.error.request_id);
}Where do I see what was billed?
The docs call GET /v1/usage the authoritative billing record. After you add funds, resubmit with the same Idempotency-Key so a request that did reach a job returns that job rather than a second one. Insufficient credits 402 has the full recovery steps.
Sources
Related posts
More in Developers
- Image 1.0 input_urls, n and format: deprecated names to replace
Sume's Image 1.0 still accepts input_urls, n and format, but prefers image_urls, num_images and output_format. What each maps to and their limits.
- Image 1.0: text, reference or masked edit - which fields to send
Image 1.0 uses prompt only for text-to-image, prompt plus image_urls for edits or references, and adds mask_image_url for masked edits. Fields and URL rules.
- mask_image_url or mask_url? Masked edits on Sume's image APIs
Image 1.0 takes mask_image_url with image_urls; POST /v1/images takes mask_url with input_references for GPT Image 2.5. Field names, models and limits.
- Image job metadata on Sume: stored on the job, not sent upstream
The metadata field on Image 1.0 and POST /v1/images is stored on the job and not sent to the provider. Use it to tie jobs to your own records.
Written by Sume