Authentication
One scheme: an API key as a bearer token in the Authorization header. There are no signed requests, no query-string keys and no cookies
curl "https://api.blocktronics.xyz/v1/account" \
-H "Authorization: Bearer <YOUR_API_KEY>"How keys work
- Sign in on the site with your wallet, then make keys on your account page. They belong to that wallet's account
- A key is btak_ followed by 32 letters and digits. The full key is shown once, at creation, and stored hashed. It cannot be recovered, only rotated
- The same keys connect the Blocktronics MCP to your AI app. One key can do both
- Each key has an end you choose when you make it: a key for your own server never ends unless you set a date; a key for an AI app that can't sign in ends after 7 days by default and 30 at most. Rotate on a schedule that suits you (the old key can keep working beside the new one for up to a week), and immediately if one leaks
- Every key on an account draws from the same credit balance. A key can also carry its own daily credit limit
- A key the site doesn't know, or one revoked or past its end, is refused with
401before anything runs
Agents: a key from your own wallet
An agent that holds its own wallet can get a key with no person and no browser. It asks for a message with POST /v1/auth/nonce, signs it with its wallet (a signature, not a transaction), and sends the signature to POST /v1/auth/key. The key comes back once. If the wallet has no account yet, one is made for it
- The account starts with no credits. It tops up from the same wallet with
POST /v1/topup/quote, with no one to allow it - Nothing free comes with an account made this way: no starter credits and no free first dashboard or hub. New accounts are limited per address each day (an IPv6 address counts by its /64), and in all
- A wallet that already has a person's account gets a new key on it, the same as signing in on the site, but held to an agent's limits: 20 credits a day, asking first above 10, nothing taken live, and it ends in 7 days. It shows on that account's keys, where the owner can change that
DELETE /v1/auth/keywith a key revokes it at once. Smart-contract wallets can't sign in yet: use an ordinary wallet
import os, requests
from eth_account import Account
from eth_account.messages import encode_defunct
API = "https://api.blocktronics.xyz/v1"
wallet = Account.from_key(os.environ["AGENT_PRIVATE_KEY"]) # the agent's own wallet
# 1. The message to sign (single use, 10 minutes).
n = requests.post(f"{API}/auth/nonce", json={"address": wallet.address}, timeout=30).json()
# 2. Sign it: a signature, not a transaction. It costs nothing.
sig = wallet.sign_message(encode_defunct(text=n["message"])).signature.hex()
# 3. The key (shown once). A wallet with no account gets one now, with no credits.
k = requests.post(f"{API}/auth/key", json={"nonce": n["nonce"], "signature": "0x" + sig.removeprefix("0x"), "name": "my agent"}, timeout=30).json()
os.environ["BLOCKTRONICS_KEY"] = k["key"] # keep it secret; then top up: POST /v1/topup/quoteKeep keys server side
A key in browser JavaScript is a public key, whatever the variable is called; anyone can read it out of the bundle or the network tab and spend your credits. Call the API from your own backend and pass the result to your frontend
// app/api/token/[chain]/[token]/route.ts: runs on the server, the key never ships
export async function GET(_req: Request, { params }: { params: Promise<{ chain: string; token: string }> }) {
const { chain, token } = await params;
const res = await fetch("https://api.blocktronics.xyz/v1/tools/token_series", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.BLOCKTRONICS_KEY}`, "content-type": "application/json" },
body: JSON.stringify({ token: `${chain}:${token}`, metrics: ["holders", "netflow_usd"], days: 30 }),
});
return Response.json(await res.json(), { status: res.status });
}Auth failures
A missing key returns 401 signed_out; an unknown, revoked, ended or mistyped one 401 bad_key. A key that can't spend credits returns 403 key_scope: make a new one. None of them is charged. See errors for the full list