Aere Cloud · API reference

One key. The whole network.

Base URL https://cloud.aere.network/v1. Authentication is an API key whose hash lives in an on-chain subscription: there is no signup form and no server-side account database to breach. Every endpoint returns JSON. Every claim in these docs can be re-checked against chain 2800.

Official SDK

Skip the raw HTTP: @aere/cloud wraps every route below, zero dependencies, Node 18+ and browsers.

npm install @aere/cloud
import { AereCloud } from '@aere/cloud';
const aere = new AereCloud({ apiKey: process.env.AERE_KEY });
const anchors = await aere.anchors(5);
const { valid } = await aere.pqVerify({ scheme: 'ml-dsa-44', publicKey: '0x…', signature: '0x…', message: '0x…' });
const receipt = await aere.notarize('0x' + sha256Hex);

Source and README: git.aere.network/aere-network/aere-cloud-sdk. It also ships verifyWebhook(rawBody, signatureHeader, secret) so you never hand-roll the HMAC check.

Overview

Aere Cloud exposes three families of endpoints behind one API key:

  • JSON-RPC: keyed access to chain 2800 with per-plan rate limits, full eth_*/net_*/web3_* namespaces plus read-only QBFT methods.
  • Post-quantum verification: NIST post-quantum signature verdicts computed by the chain’s native precompiles (live since block 9,189,161), not by application code.
  • Chain data: the validator set, chain head, and the post-quantum anchor certificates, proven and independently verifiable: every 32nd block’s Falcon-512 certificate digest and seal count, parsed for you.

Authentication

Send your key in the x-api-key header on every request except /v1/health.

x-api-key: ak2800.<your 0x address>.<secret>

The key format is load-bearing: the address tells the gateway whose subscription to check. On every request the gateway computes keccak256 of the whole key string and asks the subscription contract check(address, keyHash) on chain 2800. If the chain cannot be reached, the gateway answers 503 and refuses to guess: it fails closed, never open.

We never see or store your key. It is generated in your browser (or by you), and only its keccak-256 hash is registered on-chain. There is no key table on any server, so there is nothing to leak. If you lose the key, rotate to a new one: rotation is free, only gas.

Subscribing

The free trial is fully self-serve in the subscribe panel: connect a wallet, take the key, done. Paid plans, while AERE is pre-listing, are invoiced in USDC or EUR: email [email protected] (the panel prefills the order) and we activate your subscription on-chain via grantSubscription when payment clears; your account never needs gas. Everything the panel does is plain contract calls you can also make yourself:

# 1. generate a key and hash it (any keccak-256 tool works)
KEY="ak2800.0xYourAddress.$(openssl rand -base64 24 | tr '+/' '-_' | tr -d '=')"
HASH=$(cast keccak "$KEY")

# 2. read the plan's on-chain price (the dollar list price at the published reference rate)
cast call 0xfA2375F5c30d25e0b952F5Ac07Bc292aD3C20433 \
  "plans(uint64)(string,uint256,bool)" 0 --rpc-url https://rpc.aere.network

# 3. subscribe: planId, months (1-12), key hash; pay price x months exactly.
#    plan 5 is the free trial: a real key for the cost of gas alone
cast send 0xfA2375F5c30d25e0b952F5Ac07Bc292aD3C20433 \
  "subscribe(uint64,uint256,bytes32)" 5 1 "$HASH" \
  --value 0 --rpc-url https://rpc.aere.network --private-key $PK

# 4. use the key
curl -s https://cloud.aere.network/v1/account -H "x-api-key: $KEY"

Renewals extend from your current expiry, never from the payment date; pass 0x0 as the hash to keep your existing key. List prices are in US dollars; the contract stores each plan’s price as the AERE amount at the published reference rate ($0.05/AERE until market listing, then market, applied to new subscriptions only): always read the exact amount from plans(planId) before paying. Enterprise agreements skip the token and are invoiced in EUR or USDC.

Health

GET/v1/health  no key

$ curl -s https://cloud.aere.network/v1/health
{"ok":true,"chainId":2800,"block":15220078}

JSON-RPC

POST/v1/rpc

A JSON-RPC 2.0 endpoint on chain 2800; single requests and batches both work. Allowed methods: everything in eth_* (including eth_sendRawTransaction), net_*, web3_*, and the read-only QBFT set (qbft_getValidatorsByBlockNumber, qbft_getValidatorsByBlockHash, qbft_getSignerMetrics, qbft_getPendingVotes). Validator-vote methods are refused on every tier, paid included.

$ curl -s https://cloud.aere.network/v1/rpc \
  -H "content-type: application/json" -H "x-api-key: $KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
{"jsonrpc":"2.0","id":1,"result":"0xe83aa9"}

A disallowed method answers inside the JSON-RPC envelope, so batch positions are preserved:

{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not allowed on this endpoint"}}
Mind the 512-block state window: public endpoints keep world state for 512 blocks and eth_getTransactionCount answers 0x0 beyond it instead of erroring. Details in the chain RPC docs.

WebSocket subscriptions

WSS/v1/ws

Live JSON-RPC over WebSocket, including eth_subscribe for newHeads and logs: a new head arrives roughly every half second. The WS route exposes the eth/net/web3 namespaces only, so validator-vote methods do not exist on this path at all. Authenticate one of two ways:

  • Header (servers, preferred): x-api-key: ak2800.… on the upgrade request.
  • Query (browsers, which cannot set WS headers): wss://cloud.aere.network/v1/ws?key=ak2800.…: access logging is disabled on this route so the key is not written to server logs; still prefer the header wherever you control the client.
// node, with the ws package
const ws = new WebSocket('wss://cloud.aere.network/v1/ws', { headers: { 'x-api-key': KEY } });
ws.on('open', () => ws.send(JSON.stringify(
  { jsonrpc: '2.0', id: 1, method: 'eth_subscribe', params: ['newHeads'] })));
ws.on('message', (d) => console.log(JSON.parse(d).params?.result?.number));
// → a new block number roughly every 0.5s

A bad or missing key is refused at the door with 403/401 before any socket to the node is opened.

Post-quantum verification

POST/v1/pq/verify

The verdict is computed by the chain’s native precompiles via eth_call: the response tells you which precompile answered and at what block height. Send hex fields with 0x prefixes.

schemeprecompilerequest fieldsnotes
ml-dsa-440x…0ae3publicKey (1312 B), signature (2420 B), messageNIST ML-DSA-44 (Dilithium2)
slh-dsa-128s0x…0ae4publicKey (32 B), signature (7856 B), messageNIST SLH-DSA-SHA2-128s; ~11.8 KB requests are fine here
falcon-5120x…0ae1publicKey (897 B), signedMessageFalcon reference signed-message blob
falcon-10240x…0ae2publicKey (1793 B), signedMessagesame shape as falcon-512
# a real exchange, produced by this endpoint from a NIST ACVP vector
$ curl -s https://cloud.aere.network/v1/pq/verify \
  -H "content-type: application/json" -H "x-api-key: $KEY" \
  -d '{"scheme":"ml-dsa-44","publicKey":"0x…","signature":"0x…","message":"0x…"}'
{"valid":true,"scheme":"ml-dsa-44",
 "precompile":"0x0000000000000000000000000000000000000ae3",
 "block":15220111,"chainId":2800}

# flip one bit of the signature and the chain flips the answer
{"valid":false,"scheme":"ml-dsa-44", …}

Account

GET/v1/account

Your subscription as the gateway sees it, plus usage across the last 31 days. Usage counts requests by family (rpc, pq, data).

$ curl -s https://cloud.aere.network/v1/account -H "x-api-key: $KEY"
{"address":"0xbeb3…6465","planId":0,
 "plan":{"name":"rpc-build","monthlyPriceWei":"39000000000000000000","active":true},
 "expiresAt":1790065218,"expiresAtIso":"2026-09-22T08:20:18.000Z",
 "usageLast31Days":{"rpc":1204,"pq":37,"data":12},
 "contract":"0xbe65a4f3a1fc300c262adc0fbb9c6968fcc81fa0","chainId":2800}

Console sign-in

POST/v1/console/account

Powers the account console: the same account view as /v1/account, plus the full on-chain receipt history, authenticated by a wallet signature instead of the API key: so a company admin can see the account without handling the production key. Sign this exact message with the account’s wallet (personal_sign):

Aere Cloud console login
address: <your 0x address, lowercase>
timestamp: <unix seconds, within 10 minutes>
$ curl -s https://cloud.aere.network/v1/console/account   -H "content-type: application/json"   -d '{"address":"0x…","timestamp":1787490000,"signature":"0x…"}'
{"address":"0x…","subscription":{"planId":5,"plan":{"name":"trial",…},"active":true,…},
 "usageLast31Days":{"rpc":3,"pq":4,"data":8},
 "history":[{"type":"Subscribed","planId":5,"paidWei":"0","block":15236801,"tx":"0x…"}],
 "historyComplete":true,"contract":"0x…","chainId":2800}

The gateway rebuilds the message, hashes it under the EIP-191 prefix, and recovers the signer through the chain’s own ecrecover precompile: no signature code of ours to trust. A stale timestamp or a signature by any other key answers 401. The route is read-only: rotation and renewal are transactions only your wallet can sign.

The same signed body also manages webhooks without exposing your API key: add "webhookAction":"list", or "create" (with type, url, and watch for address-activity), or "delete" (with id). Creation returns the HMAC secret once, exactly like the keyed route; private targets are refused on this path too.

Chain head

GET/v1/data/head

{"chainId":2800,"block":15225986,"hash":"0x6539…a3b0",
 "timestamp":1787477821,"baseFeeWei":"1000000000"}

Validator set

GET/v1/data/validators

The live QBFT validator set, read from consensus, not from a config file.

{"chainId":2800,"count":9,"validators":["0x1bd5…1c9d","0x4bf6…0044", …]}

Post-quantum anchors

GET/v1/data/anchors?limit=10  ·  GET/v1/data/anchors/{height}

Every 32nd block of chain 2800 (heights with height % 32 == 16, from 13,014,000) carries a Falcon-512 validator certificate: its 32-byte digest sits in the first bytes of extraData, under the block hash, and the seals themselves ride alongside. This endpoint parses that structure for you: the data no other public chain can serve.

$ curl -s "https://cloud.aere.network/v1/data/anchors?limit=2" -H "x-api-key: $KEY"
{"chainId":2800,"head":15225986,"anchorIntervalBlocks":32,"firstAnchorBlock":13014000,
 "note":"every 32nd block carries a Falcon-512 validator certificate whose digest sits in the first 32 bytes of extraData, under the block hash",
 "anchors":[
  {"height":15225968,"hash":"0x6539…a3b0","timestamp":1787477821,
   "falconSeals":9,"certificateDigest":"0x0449…3039"},
  {"height":15225936,"hash":"0xaea7…106b","timestamp":1787477803,
   "falconSeals":9,"certificateDigest":"0x9e82…511c"}]}

limit is 1–50 (default 10). A height that is not an anchor answers 400 not_an_anchor_height with the rule in the hint. Since block 14,961,456 an anchor does not finalize with fewer than six of nine valid seals; the counts you see here are the chain’s own, typically 9.

Webhooks

POST/v1/webhooks  ·  GET/v1/webhooks  ·  DELETE /v1/webhooks/{id}

The chain pushes to you. Up to 5 webhooks per account, three event types:

typefirespayload data
pq-anchorsevery new post-quantum anchor (~16s)height, hash, timestamp, falconSeals, certificateDigest
address-activityany transaction touching your watched addresshash, from, to, valueWei, block, timestamp
subscription-eventsyour account’s billing eventsthe on-chain receipt (type, planId, paidWei, tx)
$ curl -s https://cloud.aere.network/v1/webhooks -H "x-api-key: $KEY"   -H "content-type: application/json"   -d '{"type":"pq-anchors","url":"https://your-server.example/hooks/aere"}'
{"id":"wh_7e584f1d0ad0d403","secret":"<shown once, store it>", …}

Every delivery is a POST with headers x-aere-event and x-aere-signature: hex HMAC-SHA256 of the raw body, keyed with your webhook secret. Verify it before trusting the payload:

const valid = crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex')
            === req.headers['x-aere-signature'];

Delivery policy, stated plainly: 10s timeout, 3 attempts with backoff; 20 consecutive failures disable the webhook (visible in the list) until you recreate it. Targets must be public http(s): private and loopback addresses are refused at creation and re-checked at every delivery. On gateway restart, catch-up is capped at 300 blocks: webhooks are near-real-time signal; complete history lives in the data API.

Notarization

POST/v1/notarize  ·  GET/v1/notarize/{hash}

Prove a document existed no later than a moment in time: on a chain whose every 32nd block carries a post-quantum validator certificate, so the proof is built to outlive the cryptography era it was made in. Your file never leaves your hands: hash it locally, send only the 32-byte digest, we pay the gas and carry the transaction.

$ HASH="0x$(sha256sum contract.pdf | cut -d' ' -f1)"
$ curl -s https://cloud.aere.network/v1/notarize -H "x-api-key: $KEY"   -H "content-type: application/json" -d "{\"hash\":\"$HASH\"}"
{"hash":"0x2cdc…af96","txHash":"0x4949…0f51","block":15244146,
 "firstSeenAt":1787488094,"firstTime":true,
 "contract":"0x4aB392c4Aca7D9D4C16c0b60a9514c5025bd58c7","chainId":2800}

$ curl -s https://cloud.aere.network/v1/notarize/$HASH -H "x-api-key: $KEY"
{"notarized":true,"firstSeenAt":1787488094,"firstSeenIso":"2026-08-23T12:28:14.000Z",…}

The property that makes it a proof: first-seen can never be overwritten, re-notarizing answers firstTime:false with the original timestamp, enforced by the contract, covered by tests with negative controls. The contract (AereNotary) has no owner, no funds and no admin path; it is also fully permissionless, you can skip our API entirely and call notarize(bytes32) yourself, paying your own gas. The API is the convenience, not the gatekeeper.

Transfer history

GET/v1/data/transfers?address=0x…&limit=50

Transfers touching an address, split honestly along what the chain itself allows: token transfers (ERC-20/721 Transfer events) are indexed from genesis; native AERE transfers emit no events, so they are indexed from the feature’s launch block onward: the response carries both boundaries (tokenHistoryComplete, nativeSince) so you never mistake a partial answer for a full one.

$ curl -s "https://cloud.aere.network/v1/data/transfers?address=0xYourAddr&limit=5"   -H "x-api-key: $KEY"
{"chainId":2800,"address":"0x…",
 "tokenTransfers":[{"token":"0x7e84…f5e8","from":"0x…","to":"0x…",
   "valueWei":"5000000000000000","tx":"0x…","block":15245202}],
 "nativeTransfers":[{"from":"0x…","to":"0x…","valueWei":"1000000000000000",
   "tx":"0x…","block":15245105,"timestamp":1787488549}],
 "tokenHistoryComplete":true,"nativeSince":15245018,…}

POST/v1/sponsor/createAccount  ·  POST/v1/sponsor/execute  ·  GET/v1/sponsor/health

Onboard users who hold zero AERE: your backend calls with your API key, the Foundation relayer deploys the user’s passkey smart account and submits their transactions, paying the gas. The smart account validates every signature itself: the relayer never sees a user key, so even a fully hostile relayer could only waste its own gas; user funds stay out of its reach by construction. Usage is metered per account (the sponsor counter in /v1/account).

$ curl -s https://cloud.aere.network/v1/sponsor/createAccount   -H "x-api-key: $KEY" -H "content-type: application/json"   -d '{"initialOwners":[…],"salt":"0x…"}'
# the relayer deploys the account and pays the gas; see the wallet
# infrastructure engagement for the full passkey flow

Honest phase-1 limits, same as the public relayer’s: a single relayer EOA, no high availability; if it is down, users holding AERE can still transact directly. The keyed route adds authentication and metering on top of the same engine.

Rate limits

Limits are per key, per second, by plan; the gateway also meters usage for your /v1/account view. Above the limit you get 429 with Retry-After: 1.

planlist pricerequests / second
trial (5)free25
rpc-build (0)$49/mo150
data-api (2)$199/mo100
rpc-scale (1)$249/mo500
pq-verify-api (3)$299/mo50
managed-node (4)$999/mo150

Request bodies are capped at 256 KB at the gateway (1 MB at the edge). The API plans above are the developer tier; enterprise programs (post-quantum migration, dedicated chains, compliance infrastructure, managed fleets) are scoped from six figures a year and invoiced in EUR or USDC: [email protected].

Errors

statusbody errormeaning
401missing_api_keyno x-api-key header; the body repeats the key format and contract
403invalid_or_expired_keybad format, unregistered hash, or an expired subscription
429rate_limitover your plan’s per-second limit; retry after 1s
400bad_json, unknown_scheme, bad_publicKey, not_an_anchor_height, …malformed input; the hint says what to fix
413body_too_largerequest body over 256 KB
503subscription_check_unavailablethe gateway could not verify your key on-chain and refuses to guess; temporary
502upstreamthe node behind the gateway failed to answer

The subscription contract

AereCloudSubscriptionsV2 at 0xfA2375F5c30d25e0b952F5Ac07Bc292aD3C20433 on chain 2800 (explorer). Properties, each enforced by code and covered by tests with negative controls:

  • No custody. Every payment is forwarded to the Foundation treasury inside the same transaction; the contract’s balance is always zero. There is no receive(): a bare transfer to the contract reverts, so funds cannot get stuck in it.
  • Only the key hash on-chain. subscribe(planId, periods, keccak256(key)); pass 0x0 to keep the current key.
  • Extension from expiry. Renewing early never costs you time: the new expiry is max(now, current expiry) + 30 days × periods. Prepay is capped at 12 periods.
  • Never retroactive. Price changes apply to new subscriptions only; a retired plan stops selling but every paid subscription stays valid to its expiry.
  • No upgradability, no pause, no backdoor. The owner can configure plans and move the treasury target, nothing else.

Interface

function subscribe(uint64 planId, uint256 periods, bytes32 apiKeyHash) payable
function rotateApiKey(bytes32 newApiKeyHash)            // free, needs a live subscription
function grantSubscription(address account, uint64 planId,
                           uint256 periods, bytes32 apiKeyHash)  // owner only: invoice-paid customers
function check(address account, bytes32 apiKeyHash)
    view returns (bool valid, uint64 planId, uint64 expiresAt)
function plans(uint64 planId)
    view returns (string name, uint256 monthlyPriceWei, bool active)
function subs(address account)
    view returns (uint64 expiresAt, uint64 planId, bytes32 apiKeyHash)

event Subscribed(address indexed account, uint64 indexed planId,
                 bytes32 apiKeyHash, uint64 expiresAt, uint256 paidWei)
event Granted(address indexed account, uint64 indexed planId,
              bytes32 apiKeyHash, uint64 expiresAt)   // invoice-paid, distinguishable on-chain
event ApiKeyRotated(address indexed account, bytes32 newApiKeyHash)

Changelog & status

  • 2026-08-23: v1 launch: keyed JSON-RPC, keyed WebSocket subscriptions, webhooks (PQ anchors, address activity, billing events), the notarization API, keyed gas sponsorship, post-quantum verification API, account & usage, chain data endpoints (head, validators, PQ anchors, transfer history), wallet-based subscribe panel, dollar list pricing settled on-chain at the published reference rate, and a free keyed trial plan. Machine-readable spec at /cloud-openapi.json.
  • Planned next, in the open: USDC settlement for enterprise invoices, native-transfer history backfill.

Live status: /cloud-status.html runs every check in your own browser; GET /v1/health answers without a key. Support: [email protected].