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 the amount is credited to a Fluence balance in the same request. No signup, email or console visit is needed — the paying wallet is the account. This is the shortest path for an AI agent or a script to get compute on Fluence:

  1. Top up the balance with USDC through x402. The first payment from a wallet creates a Fluence account bound to 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.

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. No ETH is needed for gas — the x402 facilitator submits the transfer.
  • An x402 v2 client. The @x402/* packages (@x402/fetch, @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.

Limits​

ParameterValue
Minimum top-up0.50 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

MethodPathAuthDescription
GET/v2/x402/payment-info?amountUsd=NNoneReturns the x402 payment challenge for N USD without paying
POST/v2/x402/top-up?amountUsd=NOptionalPaid endpoint: answers 402 Payment Required without a payment, settles and credits N USD with one
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

For complete request and response schemas, see the API reference.

Step 1: Top up​

Wrap fetch with an x402 client and call the top-up endpoint. The client handles the 402 → sign → retry exchange.

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

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);

const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});

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

A successful top-up returns 200 with a JSON body carrying amountUsd, network, asset, transaction (the Base transaction hash) and payer. The PAYMENT-RESPONSE header carries the x402 settlement response.

Other responses:

StatusMeaningWhat to do
400Amount out of range or with more than two decimal places, or a malformed paymentFix the request
402Payment required, or the payment was rejected (for example, not enough USDC). The error field of the challenge says whyFix 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 with the payer address
503Top-ups are unavailable, or the payment did not reach the facilitator. Nothing was chargedRetry later
tip

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, and the amount is credited to 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 { createSiweMessage } from "viem/siwe";

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, refreshToken } = await login.json();
  • The message domain must be exactly api.fluence.dev; any other domain is rejected.
  • A nonce works once and expires 10 minutes after it is issued (see expiresAt in the nonce response).
  • Send the message exactly as signed.

Step 3: Use the API​

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

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

Access tokens are short-lived. When one expires, sign in again (step 2). A long-running agent can instead create an API key once with POST /v1/api_keys (a name, the scopes it needs and an expiresAt time) and send it in the X-API-KEY header, as described in the API introduction.

To rent compute with the funded balance, continue with CPU Cloud or GPU Cloud.