Skip to main content

Pay with x402 (for agents)

Fluence accepts balance top-ups over the x402 protocol. An HTTP client pays USDC on Base, and Fluence credits the amount to a balance in the same request. The paying wallet is the account, so the client needs no signup, email, or visit to the Fluence Console. An AI agent or a script works with Fluence in four steps:

  1. Top up the balance with USDC through x402. The first payment from a wallet creates a Fluence account for that wallet.
  2. Sign in with the same wallet (Sign-In with Ethereum) to get an access token.
  3. Call the Fluence API with that token, or create an API key with it.
  4. Rent compute with the balance.

Requirements​

  • An EVM wallet controlled by a private key (an externally owned account). Smart-contract wallets cannot sign in.
  • USDC on Base mainnet: network eip155:8453, token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. You don't need ETH for gas. The x402 facilitator submits the transfer.
  • An x402 v2 client. The @x402/* packages (@x402/fetch or @x402/axios, with @x402/evm for EVM payments) speak v2. The unscoped x402-fetch and x402-axios packages are the older v1 line and cannot read the Fluence payment challenge.

The examples are JavaScript modules for Node.js 20 or later. Install the packages they use:

npm install @x402/fetch @x402/evm viem

Save an example as a .mjs file and run it with node. Pass the wallet key in the EVM_PRIVATE_KEY environment variable.

Limits​

ParameterValue
Minimum top-up10 USD
Maximum top-up1000 USD per request
PrecisionWhole cents, at most two decimal places

1 USDC is credited as 1 USD.

Endpoints​

Base URL: https://api.fluence.dev

MethodPathCredentialsWhat it does
GET/v2/x402/payment-info?amountUsd=NNoneReturns the x402 payment challenge for N USD without paying
POST/v2/x402/top-up?amountUsd=NOptionalWithout a payment, answers 402 Payment Required. With a payment, settles it and credits N USD.
GET/v1/auth/siwe/nonceNoneIssues a single-use sign-in nonce
POST/v1/auth/siweNoneExchanges a signed Sign-In with Ethereum message for an access token
GET/v3/account/balancesAccess token or API keyReturns your balance
GET/v3/top-upsAccess token or API keyLists your top-ups, including x402 ones
GET/v3/accountAccess token or API keyReturns your account and its permissions
POST/v3/api-keysAccess token or API keyCreates an API key

The x402 and sign-in endpoints are not in the API reference. This page is their documentation. The reference covers the /v3/... endpoints.

Step 1: Top up​

Wrap fetch with an x402 client and call the top-up endpoint. The client handles the exchange: it gets the 402 challenge, signs the payment, and sends the request again.

import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);

const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
// @x402/fetch refuses to pay more than $1 per payment unless you raise the cap.
spendControls: { maxAmountPerPayment: "$10" },
});

const response = await fetchWithPayment(
"https://api.fluence.dev/v2/x402/top-up?amountUsd=10",
{ method: "POST" },
);
console.log(response.status, await response.json());

Set maxAmountPerPayment to at least the amount you top up. With the default cap of $1, the client refuses to sign, and nothing is paid.

A successful top-up returns 200:

{
"amountUsd": "10",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"transaction": "0x…",
"payer": "0x…"
}

transaction is the Base transaction hash, and amountUsd is a decimal string. The PAYMENT-RESPONSE header carries the x402 settlement response.

Other responses:

StatusMeaningWhat to do
400The amount is out of range or has more than two decimal places, or the payment is malformedFix the request
402Payment required, or the payment was rejected, for example because the wallet has too little USDC. The error field of the challenge says why.Fix the cause and pay again
409The payment was submitted and is under reviewDo not sign a new payment: the transfer may already be on chain. Contact support@fluence.ai with the payer address.
503Top-ups are unavailable, or the payment did not reach the facilitator. Nothing was charged.Retry later
tip

If you already have a Fluence account, send your API key in the X-API-KEY header, or an access token in Authorization: Bearer, with the top-up request. Fluence then credits that account instead of a wallet account.

Step 2: Sign in with the wallet​

Request a nonce, sign a Sign-In with Ethereum message with the wallet that paid, and exchange it for an access token.

import { privateKeyToAccount } from "viem/accounts";
import { createSiweMessage } from "viem/siwe";

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);

const { nonce } = await (await fetch("https://api.fluence.dev/v1/auth/siwe/nonce")).json();

const message = createSiweMessage({
domain: "api.fluence.dev",
address: account.address,
uri: "https://api.fluence.dev",
version: "1",
chainId: 8453,
nonce,
});
const signature = await account.signMessage({ message });

const login = await fetch("https://api.fluence.dev/v1/auth/siwe", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message, signature }),
});
const { accessToken, userData } = await login.json();
  • The message domain must be exactly api.fluence.dev. The API rejects any other domain.
  • A nonce works once and expires 10 minutes after it is issued. The nonce response has the time in expiresAt.
  • Send the message exactly as signed.
  • userData holds the account id and a placeholder email wallet-<address>@x402.invalid. The wallet address is the identity of the account.

The access token expires after a few minutes. The response also has a refreshToken, but the public API has no endpoint that accepts it. When the access token expires, sign in again, or create an API key once and use it instead.

Step 3: Use the API​

Send the access token as a bearer token. For example, check the balance:

curl https://api.fluence.dev/v3/account/balances \
-H "Authorization: Bearer <ACCESS_TOKEN>"

GET /v3/top-ups lists your top-ups, including the x402 ones.

Create an API key​

A long-running agent can create an API key once and send it in the X-API-KEY header. This example gives the key every scope your account has:

SCOPES=$(curl -s https://api.fluence.dev/v3/account \
-H "Authorization: Bearer <ACCESS_TOKEN>" | jq -c '.permissions')

curl -X POST https://api.fluence.dev/v3/api-keys \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d "{\"name\": \"my-agent\", \"scopes\": $SCOPES, \"expiresAt\": \"2027-10-01T00:00:00Z\"}"
  • name: 1 to 25 characters, lowercase letters, digits, and hyphens.
  • scopes: what the key may do. A key can only get scopes that your account has. GET /v3/account lists them in permissions. A call outside the key's scopes returns 403.
  • expiresAt: an RFC 3339 time in the future.

The response is 201 with the key in value and its id. The API shows the key only once, so store it. To delete a key, send DELETE /v3/api-keys/<id>.

Creating a key has no Idempotency-Key. If the response is lost, a repeated request creates a second key. List your keys with GET /v3/api-keys and delete the one whose value you didn't receive.

An agent can also use the API key with the Fluence MCP server. See Connect an AI client through MCP.

Step 4: Rent compute​

To run a CPU VM, follow CPU Cloud API: Create a VM:

  1. Choose a cluster with GET /v3/clusters, and a configuration with GET /v3/clusters/<cluster_id>/vm-offerings.
  2. Choose an OS image with GET /v3/images.
  3. Add your SSH public key with POST /v3/ssh-keys.
  4. Create a draft with POST /v3/vms and an Idempotency-Key. Add a public interface to reach the VM from the internet.
  5. Check the price with GET /v3/vms/<vm_id>/estimate.
  6. Start the VM with POST /v3/vms/<vm_id>/provision.
  7. Read GET /v3/vms/<vm_id>/interfaces until the public interface has an address in assignedIps, then connect with ssh <username>@<address>.

For GPU containers, VMs, and bare metal servers, see the GPU Cloud API.

Billing for agents​

  • CPU resources are billed per second and charged from the balance as they run. Nothing is reserved up front.
  • Fluence starts a CPU VM only if the balance can keep all your resources, including the new ones, running for at least 6 hours.
  • Terminating a VM stops billing for the VM only. Delete its disks with DELETE /v3/storages/<storage_id> and its public IP address with DELETE /v3/public-ips/<public_ip_id> to stop paying for them.
  • A wallet account has no email address, so it gets no low-balance warnings. Watch GET /v3/account/balances and top up before the balance runs out.
  • If the balance runs out and the debt exceeds 5 USD or stays unpaid for 3 days, Fluence removes your VMs. Your disks and public IP addresses stay. If the debt then reaches 20 USD or stays unpaid for 10 more days, Fluence deletes all your resources, including disks and public IP addresses.
  • GPU instances are billed by the hour from the moment they start. When the balance runs out, Fluence ends them at the next hourly charge or earlier. See GPU Cloud billing.