LEV7 documentation
Agent API
Pay-per-request read API for agents, over x402. No account, no API key.
LEV7 exposes a small set of read endpoints that an autonomous client can call and pay for per request, using x402. There is no account to create and no API key to manage: the payment is the credential.
This tier is read only. See What this tier cannot do.
How paying works
x402 activates the HTTP 402 Payment Required status. The exchange is:
- Your agent requests a resource.
- The server answers 402 with a
payment-requiredheader describing what it accepts — amount, asset, chain, and the address to pay. - Your agent retries with a signed payment payload.
- The server verifies and settles through a facilitator, then returns the resource.
No state is kept between steps, so a request either carries payment or gets a 402. There is no session to expire.
The 402 you will get
Decoding the payment-required header of an unpaid request looks like this:
{
"x402Version": 2,
"error": "Payment required",
"resource": {
"url": "https://lev7.finance/api/agent/points/stats",
"description": "LEV7 points pipeline aggregates: epochs, points, holders"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:84532",
"amount": "50000",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"payTo": "0x…",
"maxTimeoutSeconds": 300,
"extra": { "name": "USDC", "version": "2" }
}
]
}amount is in the asset's base units — 50000 is $0.05 of 6-decimal USDC.
Calling it
@x402/fetch wraps the native fetch and handles the retry for you:
import { wrapFetchWithPayment } from "@x402/fetch";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const pay = wrapFetchWithPayment(fetch, account);
const res = await pay("https://lev7.finance/api/agent/points/stats");
const stats = await res.json();Without a payment-aware client you get the 402 and can implement the handshake
yourself against @x402/core.
Endpoints
All are GET, and all return the same shapes as the site's own API.
| endpoint | price | returns |
|---|---|---|
/api/agent/points/stats | $0.05 | Published epochs, epochs paid, total and referral points, holders |
/api/agent/points/wallet/{address} | $0.05 | One wallet's points, rank, and epoch breakdown |
/api/agent/validation/{address} | $0.05 | Validated vs unvalidated LEV7 for one wallet |
/api/agent/governance/tally | $0.05 | The latest published governance tally |
/api/agent/swap/quote | $0.05 | Indicative route and price for a buy or sell |
swap/quote takes the same query parameters as the free route.
You are not charged for failures
Settlement happens only after the endpoint returns successfully. If a read fails — an unreadable database, an address that does not parse — you get the error and keep your money.
These reads are also free
Every figure here is public and unauthenticated on the site's own API. What this tier sells is machine access: a stable, priced, documented surface with the 402 handshake, rather than scraping pages. If you are building something where the free endpoints work, use them.
Over MCP
The same five reads are also an MCP server, for an agent that would rather list tools than read an OpenAPI description:
POST https://lev7.finance/api/agent/mcpStreamable HTTP transport, stateless, JSON responses — every request is
self-contained, there is no session to open. The tools are named by the
operationId of the free route each one twins, so the parameters and error
codes documented in /openapi.json apply unchanged:
| tool | price | twin |
|---|---|---|
getPointsStats | $0.05 | /api/agent/points/stats |
getWalletPoints | $0.05 | /api/agent/points/wallet/{address} |
getValidatedBalances | $0.05 | /api/agent/validation/{address} |
getGovernanceTally | $0.05 | /api/agent/governance/tally |
getSwapQuote | $0.05 | /api/agent/swap/quote |
Payment rides in the tool call's _meta rather than a header, as
@x402/mcp defines it. A call
without payment returns an error result whose structuredContent is the
same payment-requirements object the HTTP 402 carries — accepts, payTo,
the asset and its EIP-712 domain. Retry with the signed payment in
_meta["x402/payment"]; the settlement receipt comes back in the result's
_meta["x402/payment-response"].
@x402/mcp does that round trip for you:
import { createx402MCPClient } from "@x402/mcp";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const client = createx402MCPClient({
name: "my-agent",
version: "1.0.0",
schemes: [{ network: "eip155:84532", client: new ExactEvmScheme(account) }],
autoPayment: true,
});
await client.connect(
new StreamableHTTPClientTransport(new URL("https://lev7.finance/api/agent/mcp")),
);
const result = await client.callTool("getWalletPoints", { address: "0x…" });
console.log(result.structuredContent);Two properties carry over from the HTTP tier exactly. A call that fails is
not charged: the tool returns the free route's own error envelope as an
error result, and an error result is never settled. And the schema is
checked before payment: an argument the tool's input schema rejects is
refused without a payment request, so a malformed address costs nothing to
discover. initialize and tools/list are free.
What this tier cannot do
It cannot buy, stake, or vote.
Those actions require accepting the Terms and Risk Disclosures, bound to the wallet that signs the transaction, and today that acceptance is a browser flow a human completes. Whether an autonomous agent can accept on its own behalf — or whether a human principal accepts and authorises an agent wallet — is an open legal question, not a technical one. Until it is settled, the endpoints that move money or record a vote are not part of this tier.
Voting has a further requirement even for humans: it runs through staking, and staking is gated on an eligibility certificate issued per wallet. See Governance.
Network and settlement
accepts is a list, and you pick. A 402 can offer more than one chain, and
you settle on whichever you can pay:
"accepts": [
{ "network": "eip155:8453", "asset": "0x833589…2913", "extra": { "name": "USD Coin", "version": "2" } },
{ "network": "eip155:4663", "asset": "0x5fc536…d168", "extra": { "name": "Global Dollar", "version": "1" } }
]Read the network and asset from the header rather than assuming one — which chains are offered is deployment configuration and can change. A chain whose facilitator is unreachable is simply left out of the list rather than failing the request, so treat a shorter list as normal.
extra carries the EIP-712 domain you sign the transferWithAuthorization
under. Use it as given — for Global Dollar on Robinhood the domain name is
Global Dollar, not the USDG ticker, and signing under the wrong name
produces an authorization the token rejects.
Rate limits
The underlying rate limits still apply per endpoint. Paying does not raise them. If you need a higher limit, get in touch before building against one.