For the complete documentation index, see llms.txt. This page is also available as Markdown.

x402 Payments

Treza integrates the x402 protocol to enable instant, autonomous stablecoin micropayments for API access. AI agents and developers can pay for Treza services programmatically using USDC on Base or Solana, with no API keys, subscriptions, or manual billing required.

Seven endpoints are payable. The first six sell one thing per payment and need no Treza account:

  • Pay-per-video: send a prompt (and optionally a first frame), get a generated clip back.

  • Speech: send text, get an ElevenLabs voiceover back.

  • Music: describe a track, get an original Lyria 3 piece back.

  • Images: send a prompt, get an image back on the model you pick.

  • Clips: send a YouTube link, get its most shareable moment back as a captioned clip.

  • Narrated shorts: send a topic, get a finished 30-second narrated short back.

  • Credit top-up: add to the prepaid balance that pipeline runs draw from.

What is x402?

x402 is an open payment protocol built by Coinbase that uses the HTTP 402 Payment Required status code. When a client requests a paid resource:

  1. The server responds with 402 and payment instructions (price, network, recipient)

  2. The client signs a USDC payment

  3. The client retries the request with a Payment-Signature header

  4. The server verifies the payment and settles it on-chain through a facilitator, then returns the resource

Payments are instant, permissionless, and settled in USDC on Base (L2) or Solana.

How Treza Uses x402

Endpoint
Method
Price
Description

/api/x402/video

POST

from $0.42

Generate a video from a prompt or a first frame, returned in the same response when it renders within 45 seconds. Priced by model and clip length

/api/x402/speech

POST

from $0.02

Turn text into an ElevenLabs voiceover (MP3), returned in the same response. Priced per character

/api/x402/music

POST

from $0.06

Generate an original Google Lyria 3 track from a description

/api/x402/image

POST

from $0.02

Generate an image on Nano Banana, GPT Image 2, Seedream, FLUX or Recraft. Priced by model and setting

/api/x402/clip

POST

from $0.04

Clip a YouTube link: its most shareable moment as a captioned vertical clip. Priced by the source's length

/api/x402/short

POST

from $0.87

A finished 30-second narrated short from a topic: script, scenes, narrator, music, captions

/api/billing/credits/x402

POST

$5.00

Top up a prepaid credit balance

Networks

Every 402 challenge from every endpoint lists two ways to pay the same amount, Base first:

Chain

network

USDC (asset)

Gas in your wallet

Base mainnet

eip155:8453

0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913

None: the payment is an EIP-3009 authorization the facilitator submits

Solana mainnet

solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp

EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

None: the facilitator pays the network fee (extra.feePayer)

An x402 client pays the first entry it has a wallet for. A client with an EVM wallet pays on Base, and a client with a Solana wallet pays on Solana (see Paying from a Solana wallet). Your wallet needs USDC on the chain it pays from, and nothing else.

Paid on Solana, the response's network is solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp, transaction is a base58 transaction signature rather than a 0x hash, and payer is your base58 address. A Base wallet and a Solana wallet are separate Treza wallet accounts: credit left on one is not visible to the other.

Pay-Per-Video

POST /api/x402/video generates a video from a text prompt, or animates an image from its first frame. It returns the video in the same response when the render finishes within 45 seconds, otherwise a statusUrl to collect it from. Pay once per clip. No Treza account, API key, or signup is required. The payment is the only credential.

Price

Price is quoted per request and depends on the model and the clip length. Read it off the 402 challenge rather than hard-coding it. Each model sells its own lengths:

model

Prices (USDC)

minimax-h3 (default)

5 s $0.42, 10 s $0.84, 15 s $1.26

veo-3.1-lite

4 s $0.45, 6 s $0.68, 8 s $0.90

wan-2.7

5 s $0.70, 10 s $1.40

veo-3.1-fast

4 s $0.68, 6 s $1.01, 8 s $1.35

kling-3.0

5 s $0.89, 10 s $1.77, 15 s $2.65

kling-3.0-pro

5 s $1.18, 10 s $2.36, 15 s $3.53

seedance-2.5

5 s $1.64, 10 s $3.27, 15 s $4.90

veo-3.1

4 s $2.24, 6 s $3.36, 8 s $4.48

16:9 and 9:16 cost the same, and so does a clip that starts from an image_url. The cheapest clip is $0.42 and the most expensive is $4.90.

Models

Send model to pick one. Omit it and the default renders, unless you send an image_url: then the cheapest model that takes an image at the length you ask for renders it, and the 402 quotes that model's price.

seconds, with an image_url and no model

Renders on

5 or 10

wan-2.7

15

kling-3.0

4, 6, 8, or none

veo-3.1-lite

So {"prompt": "...", "seconds": 5, "image_url": "..."} buys a 5-second clip on wan-2.7 for $0.70. Naming minimax-h3 with an image_url is refused, since it renders from text only.

model

Model

First frame

Worth knowing

minimax-h3 (default)

MiniMax Hailuo 3

No

768p with native audio, and the fewest prompt refusals of anything we run. The right choice unless you have a reason to pay more. Text only: it cannot take an image_url

veo-3.1-lite

Google Veo 3.1 Lite

Yes

Google Veo at its lowest price, with native audio, usually ready in about a minute. Google's safety filter returns nothing for some prompts; that is not charged and can be retried

wan-2.7

Alibaba Wan 2.7

Yes

Native audio at 5 or 10 seconds, and the most permissive with photos of real people as a first frame

veo-3.1-fast

Google Veo 3.1 Fast

Yes

Sharper Veo with native audio, typically under two minutes

kling-3.0

Kling 3.0

Yes

720p with native audio

kling-3.0-pro

Kling 3.0 Pro

Yes

Kling's higher-fidelity tier, 720p with native audio

seedance-2.5

ByteDance Seedance 2.5

Yes

720p with native audio and higher fidelity, at about four times the price of the default. Its content filter is strict: prompts that resemble a brand, a broadcast, or a famous scene are refused, and so are photos of real people. A refusal is not charged, and the response carries a retryUrl that renders a reworded prompt without paying again

veo-3.1

Google Veo 3.1

Yes

Google's top-fidelity model with synchronized audio, for final shots

A model value that is not on this list is refused with a 400 before any payment moves, naming the ones that are. Nothing is ever silently swapped for the default.

To read the current list and prices programmatically, GET /api/x402/video with no query parameters. It returns every model on sale with what it is for, whether it takes a first frame, and its prices, plus the request fields, the limits, and how delivery works. No payment or credential is needed.

Abridged (notes and most of the 46 offers left out):

Request

Field
Required
Default
Notes

prompt

Yes

none

What the video should show. Max 2000 characters

seconds

No

the model's shortest

A length the model sells (see Price). Drives the price. Also accepted as duration or durationSeconds

aspectRatio

No

16:9

16:9 or 9:16. Also accepted as aspect

model

No

minimax-h3; with an image_url, the cheapest model that takes one at your length

One of the ids in Models. Drives the price

image_url

No

none

First frame (image-to-video): a public https JPEG, PNG or WebP up to 10 MB. It is cropped to the aspectRatio you buy (1280x720 or 720x1280) and the video starts from it. Every model except minimax-h3 takes one. Also accepted as imageUrl

async

No

false

true answers 202 at once with a statusUrl to poll, instead of waiting for the render

These fields are the whole request; they are also accepted nested under "inputs". A request asking for a length or model that is not on sale, sending an image_url with minimax-h3, or carrying any field the endpoint does not read, is refused with a 400 before the payment settles, so a malformed call costs nothing, and nothing you send can be silently ignored and paid for.

An image_url is checked before the payment settles too, so an image that cannot be used is refused with nothing charged. The URL and the model are checked first; then the image is downloaded, and it must be fetchable within 4 seconds. Every image_url refusal carries a code alongside an error that says what to fix:

code

Status

Meaning

IMAGE_URL_INVALID

400

Not a plain https URL: http, a username or password, or a non-default port

IMAGE_URL_BLOCKED

400

Points at a private, loopback or internal host. Host the image somewhere public, such as a CDN or a public bucket

IMAGE_MODEL_MISMATCH

400

Sent with minimax-h3, which renders from text only. Name another model, or leave model out

IMAGE_FETCH_FAILED

400

The download failed: the host did not resolve, answered an error, or took longer than 4 seconds

IMAGE_TOO_LARGE

413

Larger than 10 MB

IMAGE_UNSUPPORTED_TYPE

400

Not a JPEG, PNG or WebP

IMAGE_DIMENSIONS

400

Short edge under 256 px, an edge over 8000 px, over 40 megapixels, or a shape beyond 4:1

IMAGE_STORE_FAILED

503

The image was fine but could not be stored on our side. Try again

Flow

The payment settles before the render starts. The paid call then waits up to 45 seconds: a clip that renders in time comes back in the same response, and a longer render leaves you a statusUrl to collect it from. The 45-second default keeps the whole call inside fixed client timeouts, such as the 60 seconds an MCP tool call allows, so your client always receives its claim ticket.

Any x402 client signs and retries for you. The paid response is streamed:

  1. Status 200 and the headers arrive at once. X-Status-Url carries the statusUrl, so you hold the claim ticket before the render has finished.

  2. While the render runs, the body is a whitespace byte every 2 seconds. JSON parsers ignore leading whitespace, so res.json() reads the body as usual.

  3. The body ends with one complete JSON object: the result, or "status": "running" once the wait is over.

The HTTP status is 200 whatever happened to the render, so read status in the body. When the video is ready:

Use the video URL exactly as given, query parameters included. When you sent an image_url, it is echoed back as imageUrl. Paid on Solana, network, transaction and payer take their Solana forms (see Networks).

If the render takes longer than the wait (45 seconds by default), the body ends with "status": "running" instead:

Then poll statusUrl until status is no longer running. The token in the URL is the only credential it needs, and polling is free. Use the URL exactly as given: the runId contains #, which must stay encoded as %23. To long-poll instead, send Prefer: wait=N and the status call holds its answer until the run finishes, for up to N seconds (at most 720), streamed the same way:

Waiting longer. If your client can hold a connection open, send Prefer: wait=N on the paid call to wait up to N seconds instead of 45, at most 720.

Getting the status URL at once. To have the paid call answer immediately and poll yourself, send "async": true in the body or the header Prefer: respond-async. The paid call then answers 202 with the runId, statusUrl and pollAfterMs, as in the running body above.

Both the 200 and the 202 carry the statusUrl in an X-Status-Url header, and a Preference-Applied header echoes the preference that was honoured (respond-async, or wait=N).

A render that outlasts its deadline. Occasionally a provider finishes a clip after the render's own deadline. The run then reads "status": "running" with a note while the clip is collected from the provider, and turns success with the video when it arrives. Keep polling; a retry is refused (409) meanwhile, because the clip is still coming.

When a render fails

A render can fail after the payment has settled, most often because the model declined the prompt or the image. Nothing is charged for a failed render, so the payment stays on your wallet's account and the retry spends it instead of costing you again.

The response for a failed run, from the paid call or from statusUrl, carries what went wrong and what to do about it:

Field
Notes

status

error or partial (occasionally cancelled)

reason

prompt_refused means the model declined the prompt or image, so reword it. render_failed means the render did not finish, and the same prompt may succeed

retryable

true until the run's one free retry has been used, then false

retryUrl

Where to retry. It carries the same signed ticket, so it needs no other credential. Gone once the run has been retried

message

What happened and what to do, in one sentence

balanceUsd

Credit left on your wallet's account, which the retry spends

POST the retryUrl to render again without paying twice. Send {"prompt": "..."} to reword, which is the fix for prompt_refused, or send no body to run the original prompt again. The retry renders the same model, length, shape and first frame the failed run was sold, and each failed run can be retried once. Like the paid call, the retry waits up to 45 seconds by default (Prefer: wait=N for longer, at most 720) and ends with the result or with "status": "running" and its own statusUrl; send {"async": true} or Prefer: respond-async for an immediate 202 with a new runId and statusUrl.

Once a run has been retried, its own status (and a second retry attempt, which answers 409) points at the retry with retriedBy, so a lost retry response never loses the clip. Poll retriedBy.statusUrl for the result:

Billing

Your payment credits an account keyed to your wallet address, and the render is charged against that balance. Anything left over stays as credit for your next call. The same wallet always maps to the same account, and a Base wallet and a Solana wallet are separate accounts.

A failed render is not charged, so the payment remains available for a retry.

Each payment buys one render. A payment presented again after it was redeemed is refused with a 409, and nothing new is rendered or charged:

Full example

Paying from a Solana wallet

The same purchase from a Solana wallet, with @x402/fetch, @x402/svm, @solana/kit and bs58. The secret key is the base58 64-byte export from Phantom and most wallets. The wallet needs USDC on Solana and no SOL.

ExactSvmScheme reads the USDC mint from a Solana RPC; pass { rpcUrl } as its second argument to use your own instead of the public endpoint.

A worked example is at trezalabs.com/x402, and a complete buyer script, which pays on Base or Solana, is at treza-labs/x402-video-example.

Speech, Music and Images

Three more endpoints sell the same way as pay-per-video: POST the body, pay the 402, and the paid response ends with the file. Each is its own resource, with its own listing in the x402 Bazaar. A bare GET on any of them returns its menu (every option and price), and an unpaid POST returns the 402 quoting the exact price for your body. Only the documented fields are read; anything else is refused with a 400 before payment.

The response is the same streamed shape as pay-per-video: 200 at once with the X-Status-Url header, a whitespace byte every 2 seconds, then one JSON object whose status is success, error (with retryUrl) or running (poll statusUrl). The file URL is under audio for speech and music, and image for images. Use it exactly as given. These usually finish in 3 to 25 seconds, well inside the 45-second default wait. "async": true or Prefer: respond-async answers 202 with a statusUrl instead. A failed generation charges nothing, and POST <endpoint>/retry?runId=...&token=... (the retryUrl) tries again on the balance the payment left, once, optionally with a reworded text or prompt.

Speech: POST /api/x402/speech

Text in, an ElevenLabs voiceover (MP3) out.

Field
Required
Values

text

yes

Up to 3,000 characters. input is accepted as a synonym

voice

no

george (default), daniel, callum, alice, lily, brian, adam, asher, archie, mark, piper, rachel, charlie

model

no

eleven-v3 (default): the most expressive read; performs directions in square brackets, e.g. [whispers], without speaking them. eleven-multilingual-v2: the steadiest read for long narration, 29 languages

async

no

true for a 202 and a statusUrl

Price: $0.42 per 1,000 characters, rounded up to the cent, minimum $0.02 (1,000 characters is about a minute of speech). The response echoes characters, the count the price was computed from.

Music: POST /api/x402/music

A description of the sound you want in, an original track out.

Field
Required
Values

prompt

yes

Genre, mood, instruments, tempo. Up to 2,000 characters

model

no

lyria-3-clip (default): a 30-second piece, $0.06. lyria-3-pro: a full-length song, $0.12

async

no

true for a 202 and a statusUrl

Images: POST /api/x402/image

A prompt in, one image out, on the model you pick.

Field
Required
Values

prompt

yes

Up to 2,000 characters

model

no

See the table below. Defaults to nano-banana

aspectRatio

no

Defaults to 1:1. Each model sells its own shapes

resolution

no

Only on the models priced by resolution

quality

no

Only on gpt-image-2

async

no

true for a 202 and a statusUrl

model

Shapes

Price

nano-banana (Google, default)

1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 4:5, 5:4, 21:9

$0.06

nano-banana-2 (Google)

same as above

resolution 512 $0.07, 1K $0.10 (default), 2K $0.15, 4K $0.22

nano-banana-pro (Google)

same as above

resolution 1K $0.20 (default), 2K $0.20, 4K $0.35

gpt-image-2 (OpenAI)

1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9

quality low $0.02, medium $0.10 (default), high $0.36

seedream-5-pro (ByteDance)

1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 4:5, 5:4, 21:9

resolution 2K $0.13 (default), 1K $0.07

flux-2-pro (Black Forest Labs)

1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9

1:1 $0.05, 21:9 $0.09, other shapes $0.07

recraft-v4.1 (Recraft)

1:1, 16:9, 9:16, 4:3, 3:4

$0.05

A setting the model does not offer (a resolution on gpt-image-2, a shape Recraft does not render) is refused with a 400 rather than silently dropped, so what you pay for is what renders.

The buyer scripts in treza-labs/x402-video-example cover these too: npm run buy:speech, npm run buy:music and npm run buy:image.

Clips and Narrated Shorts

Two endpoints sell finished edits rather than one generation. Both render on our worker in a few minutes, so the paid response usually ends after its 45-second wait with "status": "running" and a statusUrl: poll it (send Prefer: wait=600 to hold one request open instead). Both return the file as video.

If one of these fails part way (a scene the video model refuses, a download YouTube blocks), the steps that finished are charged and the rest of the payment stays on your wallet balance. The free retry (retryUrl) with no body resumes the failed run: finished steps are reused, not re-billed, and only what failed runs again.

Clips: POST /api/x402/clip

A YouTube link in; its most shareable 30 to 60 seconds out, cut and reframed on the speaker, with burned-in captions. outputs.moment carries the pick as JSON: start, end, and a title and caption to post it with.

Field
Required
Values

url

yes

A YouTube video link: a watch page, a Short, or a youtu.be link. Other sites, playlists and channels are refused

aspectRatio

no

9:16 (default), 4:5, 1:1 (all cropped on the speaker), or 16:9 (the original framing)

async

no

true for a 202 and a statusUrl

Price: by the source's length, $0.02 plus $0.005 a minute, times the 1.4 markup, rounded up to the cent. About $0.12 for a 12-minute video, $0.45 for an hour; sources up to 2 hours. The video is looked up before you pay, so the 402 quotes the exact price for your link, and a video that cannot be clipped (private, age-restricted, live, missing, too long) is refused with a 400 and a code before any payment moves. Clip only videos you have the rights to use.

Narrated shorts: POST /api/x402/short

A topic in; a finished 30-second vertical short out: a written script, four scenes, an ElevenLabs narrator, a music bed, word-by-word captions and callout cards. outputs.title and outputs.description come with it.

Field
Required
Values

topic

yes

What the short is about, up to 500 characters

style

no

motion (default, $3.22): each scene animated with Google Veo 3.1 Lite. stills ($0.87): the same edit on generated stills with a slow push-in

voice

no

The narrator, one of the speech voices (default brian)

async

no

true for a 202 and a statusUrl

Funding an Account Without a Human

This is the one most agents want. Pipeline runs draw a prepaid credit balance, and an agent holding a wallet can refill that balance itself, with nobody signing in to a billing page.

Ask what the balance is and how to add to it, using get_credit_balance over MCP or GET /api/account/balance with an API key:

An x402 block means agent-native top-up is available on this deployment, and networks lists the chains it accepts, Base first. topUpUrl is the human path; the rest of this page is the other one.

Paying the endpoint

PAYMENT-SIGNATURE carries the payment and is the only required header.

Authorization is optional and selects which account is credited. Send a Treza credential (API key, OAuth token, or session) to credit that account; send none and the credits go to an account keyed to the paying wallet address (a Base wallet and a Solana wallet are separate accounts). The example pays on Base; a Solana wallet pays the same way with ExactSvmScheme, as in Paying from a Solana wallet.

A successful call returns the grant and the transaction that paid for it:

Call it again to add another $5. The credits are spendable immediately.

The wallet needs USDC on Base mainnet (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) or on Solana mainnet (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). Neither needs gas money: on Base the facilitator broadcasts the transfer, and on Solana it pays the network fee.

Paying twice for the same thing is not possible

The ledger entry is keyed to the settled transaction (a hash on Base, a signature on Solana), so a repeated request credits once and answers "duplicate": true. On Base a replayed payment usually does not even reach that check: the authorization nonce is already spent on-chain, and the facilitator rejects it.

When a payment is refused

The response says why, rather than repeating the challenge:

Message
Meaning

invalid_payload: ... execution reverted

The wallet cannot cover the payment

invalid_payload: authorization nonce already submitted

This payment was already spent

Invalid or expired credentials

The bearer is wrong, or the key lacks a pipelines: scope

x402 payments are not configured on this deployment

Agent-native top-up is off here; use topUpUrl

Authorization is checked before the payment settles, so a request refused for a bad bearer costs nothing.

Payment Flow

The pay-per-video call end to end. The request, and any image_url, is checked after the payment verifies and before it settles, and the payment settles before the render starts. The response then stays open until the render finishes, for up to 45 seconds by default.

Client-Side: Paying for Treza Services

Using the Treza SDK (Enclave as Wallet)

A Treza Enclave can act as the payment wallet itself, keeping the private key inside the hardware-isolated TEE. This is optional; any viem-compatible account works just as well.

Install Dependencies

Auto-Paying Fetch

The simplest approach. createEnclaveFetch returns a fetch function that automatically handles 402 responses:

x402 Client (Advanced)

For more control, use the x402 client directly:

Enclave Account (Low-Level)

Create a viem-compatible account backed by the enclave for use with any x402 library:

Using Any x402 Client (External Wallet)

You don't need the Treza SDK to pay. Any x402-compatible wallet works:

Using curl (Manual)

To inspect the 402 response without paying:

Decoded, the challenge carries the price for the model and clip length you asked for, once per chain (abridged):

Amounts are in token atomic units (USDC has 6 decimals on both chains, so the price times 1,000,000): 420000 is 0.42 USDC and a $4.90 clip is 4900000. Pay to the payTo the challenge names rather than a copied address.

Server-Side: Adding x402 to Your Own Endpoints

If you're building on the Treza platform and want to monetize your own API endpoints, use the withX402Payment wrapper.

Basic Usage

With Bazaar Discovery

Make your endpoint discoverable by AI agents on the x402 Bazaar:

Declare method and bodyType for any route that takes a request body. Without them the listing describes the route as query-parameterized, and an agent will send its arguments in the URL of a request that only reads JSON.

Environment Variables

Variable
Required
Default
Description

X402_ENABLED

No

false

Set to true to enable x402 payment gating

TREZA_X402_PAY_TO

Yes (if enabled)

none

Base wallet address that receives USDC payments

TREZA_X402_PAY_TO_SOLANA

No

none

Solana address that receives USDC payments. When set, and the facilitator settles Solana mainnet, every 402 lists a Solana entry after the Base one

X402_NETWORK

No

eip155:8453

Network identifier (Base mainnet)

X402_FACILITATOR_URL

No

https://api.cdp.coinbase.com/platform/v2/x402

Payment verification facilitator

X402_CDP_API_KEY

Yes (CDP mainnet)

none

CDP API key id; the CDP facilitator authenticates every call

X402_CDP_API_SECRET

Yes (CDP mainnet)

none

CDP API key secret

X402_TOPUP_USD

No

5

USD credited per successful top-up call

X402_VIDEO_PIPELINE

No

pipeline_x402_video

The one published pipeline every pay-per-video purchase renders on

X402_VIDEO_WAIT_MS

No

45000

How long a paid call waits for the render by default before answering with status running, in ms. Capped at 720000; 0 answers 202 by default. Leave it unset rather than empty, since an empty value reads as 0

Testnet Configuration

Mainnet Configuration

Discovering Payable Services

AI agents can discover Treza's x402-payable endpoints through the Bazaar:

Security Model

Layer
Protection

TEE Signing

Payment signatures are created inside the hardware-isolated enclave, so private keys never leave the Nitro Enclave boundary

Attestation Verification

Optional pre-signing attestation check ensures the enclave is untampered before authorizing payments

Facilitator Verification

Payment signatures are verified by the Coinbase facilitator before the server returns data

On-Chain Settlement

Payments settle as real USDC transfers on Base or Solana, providing an immutable audit trail

Replay Protection

Each payment signature is bound to a specific request and cannot be reused

Architecture

FAQ

Do I need USDC to use Treza? Only if x402 is enabled on the endpoint you're calling. During development and on testnet, x402 is disabled by default.

Which chains? USDC on Base mainnet or Solana mainnet. Every 402 challenge lists both at the same price, Base first, and your client pays with whichever wallet it has; neither chain needs gas money in your wallet. A Base wallet and a Solana wallet are separate accounts, so credit left on one is not visible to the other. Testnet deployments use Base Sepolia.

What if I send the same payment twice? It is redeemed once. A second video request with the same payment answers 409 with code: "PAYMENT_ALREADY_REDEEMED" and renders nothing, and a second top-up credits nothing and answers "duplicate": true. Send a new payment to buy again.

Can I use a regular wallet instead of an enclave? Yes. Any viem-compatible account or x402 client works. The enclave-as-wallet pattern is optional; it just adds the security of TEE-based key management.

How much do API calls cost? Video generation is priced by model and clip length, from $0.42 for a five-second clip on the default model to $4.90 for fifteen seconds on Seedance 2.5; the 402 challenge quotes the exact figure for what you asked for, and GET /api/x402/video lists every model's prices. Credit top-up is $5.00 per call.

Do I have to poll for the video? Not for quick renders. The paid call returns the video URL in the same response when the render finishes within 45 seconds, and Prefer: wait=N waits longer (at most 720 seconds). Poll statusUrl when the body ends with "status": "running", when you sent "async": true, or when your connection dropped: the X-Status-Url header gave you the URL before the render finished.

Can I animate my own image? Yes. Send image_url, a public https JPEG, PNG or WebP up to 10 MB, and the video starts from it, cropped to the aspect ratio you buy. Every model except minimax-h3 takes one. Without a model, the cheapest model that takes an image at your length renders it: wan-2.7 for 5 or 10 seconds, kling-3.0 for 15, veo-3.1-lite for 4, 6, 8 or no length. The image must be fetchable within 4 seconds, and it is checked before the payment settles, so one that cannot be used costs nothing.

Do I need a Treza account? No, for either x402 endpoint. Video generation needs only the payment, and credit top-up without a bearer credits an account keyed to your wallet address. An account is required for the pipeline API.

What if the render fails? A failed render is not charged. The payment stays as credit on your wallet's account, and the response carries a retryUrl you can POST to render again without paying twice, optionally with a reworded prompt. See When a render fails.

Is there a minimum balance? No minimum. You just need enough USDC in your wallet to cover the call price.

Last updated