Authentication & keys
You need at most one key, and even that one is optional.
| Key | Where to get it | What it unlocks |
|---|---|---|
AURADEFI_ETHERSCAN_API_KEY |
etherscan.io/apis, free tier | EVM balances and history on every eip155:* chain |
Nothing else takes a key. DefiLlama prices, Blockstream Esplora for Bitcoin and the public Solana endpoint are all keyless, and Sandbox is a recording that makes no network call at all. Webhooks run the other way: we sign, you verify.
There is no auradefi account, no dashboard and no credential of ours to obtain. The key above belongs to a third party, and you bring it.
Environment variables
All configuration is read by Settings.from_env(), which Auradefi.from_env()
calls. Copy .env.example
and fill in what you need.
| Variable | Default | Meaning |
|---|---|---|
AURADEFI_ETHERSCAN_API_KEY |
none | Etherscan V2 key. Optional. |
AURADEFI_HELIUS_API_KEY |
none | Parsed but not yet consumed. See Solana below. |
AURADEFI_HTTP_TIMEOUT_S |
10.0 |
Timeout for clients the library builds for you. |
AURADEFI_SYNC_MIN_INTERVAL_S |
60 |
Floor between two ticks for one connection. |
AURADEFI_PROJECT_ID |
embed |
Namespace for derived tenant ids. |
AURADEFI_TRUSTED_PROXY_HOPS |
0 |
How many X-Forwarded-For hops your proxies add. |
The AURADEFI_ prefix is mandatory. A bare ETHERSCAN_API_KEY in your shell
is ignored on purpose, so an unrelated variable can never silently become this
library's credential. A test pins that behaviour.
Etherscan V2
This is the only key worth setting.
export AURADEFI_ETHERSCAN_API_KEY=… # https://etherscan.io/apis
It is optional. Without it the apikey parameter is omitted from the request
entirely, rather than sent empty, and Etherscan's keyless tier applies.
One key covers every EVM chain. The chain travels in the request as chainid,
derived from the CAIP-2 id, so Ethereum, Polygon, Base and any other
eip155:N Etherscan supports all use the same key.
The free tier allows 3 requests per second and 100k per day, and what one call costs against that allowance is on Limits and cost.
A wrong or revoked key is not a distinct error type. Etherscan answers HTTP
200 with {"status": "0", "message": "NOTOK", "result": "Invalid API Key"},
which surfaces as:
auradefi.errors.SourceError: etherscan balance error: message='NOTOK' result='Invalid API Key'
An empty history is a valid answer rather than an error. status: "0" with
"No transactions found" is an empty page, because a fresh address is a valid
address.
DefiLlama
There is no key to set. Two limits matter more than the credential does.
It covers six chains: ERC-20 prices resolve on chain ids 1, 10, 56, 137, 8453 and 42161, and native coin prices resolve on the four ETH-native ones.
It has no Bitcoin or Solana prices at all. Nothing in this package can price
BTC or SOL. Those assets come back held but unpriced: listed in
report.holdings with price=None, named in report.unpriced, and never
counted as zero. To price them, bind your own prices port, described in
Bring your own.
Bitcoin
Esplora needs no key. The base URL is the network selector:
Esplora(client) # mainnet Esplora(client, base_url="https://blockstream.info/testnet/api")
The thing to budget for here is request volume, which Limits and cost puts a number on.
The extended public key never leaves your process. Every request carries a
derived bc1… address, and the test suite asserts that against recorded
traffic.
Solana
The public mainnet-beta endpoint needs no key and is aggressively rate-limited
upstream; a 429 surfaces as SourceError: solana rpc HTTP 429. For a keyed
provider, pass the entire URL. AURADEFI_HELIUS_API_KEY is parsed by
Settings and consumed by nothing, because the Helius adapter does not ship:
SolanaRpc(client, url="https://mainnet.helius-rpc.com/?api-key=…")
Solana transaction decode is not implemented. Balances and signature history only.
Webhooks
Here the direction is reversed: you hold no key of ours, because we sign and
you verify. Each endpoint gets a secret, shown once at registration, and every
delivery carries X-Auradefi-Signature (HMAC-SHA256 over timestamp.body)
plus X-Auradefi-Timestamp. The verifier ships:
from auradefi.webhooks.sign import verify_signature verify_signature(secret, timestamp_ms, raw_body, signature, now_ms)
It compares in constant time and refuses a stale timestamp, which gives a captured request a shelf life. See guide 09.
The HTTP API's own credentials
If you run the HTTP API, it has a second, unrelated credential model, and these credentials are yours to issue.
adk_live_… and adk_test_… server keys are created by your backend and
scoped (users:admin, accounts:read, accounts:write, sync:trigger).
They are stored as hashes, so a database dump does not yield working
credentials.
Short-lived user tokens are minted from a server key for exactly one end user and signed with that project's secret. They are safe for a browser or a mobile app, and a token from one project can never verify under another's secret.
What CassetteMissError means
If you are in Sandbox and see this, nothing is broken and no credential is missing:
auradefi.errors.CassetteMissError: GET https://api.etherscan.io/… is not recorded in sandbox.json. Recorded interactions: …
It means you asked for something the recording does not contain, usually a
different address, chain or page size. Three ways out: ask for what the
recording holds, which Quickstart lists;
switch to from_env() with a real key; or
record your own once and replay it
offline after that.