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: the official clients wrap every route below, with zero dependencies, in five languages. They are installed from the repository: they are not on the npm or PyPI registries yet, and a package there with a name like ours is not ours.

npm install git+https://git.aere.network/aere-network/aere-cloud-sdk.git                          # JavaScript, Node 18+ and browsers
pip install "git+https://git.aere.network/aere-network/aere-cloud-sdk.git#subdirectory=python"   # Python
go get git.aere.network/aere-network/aere-cloud-sdk/go@main                                        # Go

Java: build java/ in the same repository with the JDK alone (built against the Java 8 API since 1.6.1). .NET: build csharp/Aere.Cloud with the .NET SDK (8 or later). Go modules are also served by the Go module proxy (@v1.7.0). All five have the same routes and semantics, and none of them follows redirects, so your key is never sent to a host you did not name.

import { AereCloud } from '@aere/cloud';
const aere = new AereCloud({ apiKey: process.env.AERE_KEY });
const anchors = await aere.anchors(5);
const finality = await aere.finality(); // the block you may treat as final (SDKs 1.5.2)
const { verdict } = await aere.verify(envelope); // Trust API: VALID / INVALID / PARTIAL (SDKs 1.6.0)
const id = await aere.identityVerify({ presentation, audience, nonce, trustedIssuers }); // identity (SDKs 1.7.0)
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: the Falcon-512 certificate digest and seal count of every anchor block (every 32nd; every 128th from block 17,225,968 to block 20,746,736, 2026-09-05 to 2026-09-29), parsed for you.

Authentication

Send your key in the x-api-key header on every request except the routes marked no key: /v1/health, the readiness scan (POST /v1/pq/readiness, GET /v1/pq/readiness/{domain}), /v1/pq/finality, /v1/pq/adoption and account creation (POST /v1/console/account) (corrected 2026-10-27: this line named /v1/health alone).

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. The one subscribe call costs gas, a fraction of a thousandth of an AERE; AERE cannot be bought yet and the mainnet faucet closed on 2026-10-15, so if your wallet holds none, email [email protected] and ask for the trial to be activated for you. 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 beyond it state reads are refused with -32000 World state unavailable, and eth_call with -32603 Internal error (until 2026-09-10 eth_getTransactionCount answered a false 0x0 there, and another provider still can; corrected 2026-10-27: this note said it still does, and gave -32000 for eth_call too). 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 0.62 seconds. 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.62s

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

Internal or external interface (2026-09-17). The ML-DSA and SLH-DSA precompiles verify the FIPS internal interface: the message is checked exactly as given (that is what the NIST ACVP sigVer internal vectors exercise). A standard external signature, the kind every library, HSM and the AIP-20 tooling produces, is made over M' = 0x00 || len(ctx) || ctx || M. Pass "interface": "external" (and optionally "context", 0x-hex, at most 255 bytes) and the gateway builds M' for you; the response echoes interface. Measured on chain for ML-DSA-44 with an AIP-20 vector: raw message false, external interface true, corrupted signature false, another context false. For SLH-DSA-128s the same encoding follows FIPS 205 and has not yet been measured against an external vector; say so in your own tests.

# 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", …}

Quantum readiness scan

POST/v1/pq/readiness  ·  GET/v1/pq/readiness/{domain}

Is a domain quantum-safe on the wire? The Aere Cloud host opens five real TLS connections to port 443 of the hostname (a classical TLS 1.3 baseline; a handshake offering only the hybrid post-quantum group X25519MLKEM768; one offering it first, to see preference; a TLS 1.2-only handshake; an HTTPS HEAD for HSTS), reads the served certificate chain, and returns a score, a verdict, the measured facts and concrete recommendations. Free, no key; results are cached for six hours per domain, scans are limited per client. Certificates are reported, not penalised: no public CA issues post-quantum certificates yet. Browser version: /quantum-readiness.html.

$ curl -s https://cloud.aere.network/v1/pq/readiness -H "content-type: application/json" -d '{"domain":"aere.network"}'
{"domain":"aere.network","measuredAt":"2026-09-17T20:48:44.940Z","from":"AERE Cloud, EU (Helsinki)",
 "score":75,"verdict":"partially prepared",
 "summary":{"tls13":true,"pqKeyExchange":"X25519MLKEM768","prefersPqWhenOffered":false,
  "tls12Accepted":true,"hsts":false,"harvestNowDecryptLater":"protected for TLS 1.3 clients that offer the hybrid group",
  "certificate":{"keyType":"EC/prime256v1","bits":256,"issuer":"Let's Encrypt","daysLeft":69}},
 "findings":[{"id":"pq-not-preferred","severity":"medium",…},{"id":"tls12-accepted","severity":"medium",…},{"id":"hsts-missing","severity":"low",…},{"id":"auth-classical","severity":"info",…}],
 "handshakes":{…}, "method":"…"}

Attested reports (keyed). Add "attest": true with your API key and the SHA-256 digest of the measured report is notarized on chain 2800, so the report carries a first-seen time that cannot be backdated and is covered by the validators’ post-quantum certificate at the next anchor. The response adds attestation: reportJson (the exact UTF-8 text that was hashed; recompute sha256(reportJson) in any language and it equals reportHash), txHash, block, firstSeenAt, and proof, the path of the Proof API record for it. Attesting without a key answers 401; the scan itself never needs one. Counted as one data request.

$ curl -s https://cloud.aere.network/v1/pq/readiness -H "x-api-key: $KEY" -H "content-type: application/json" -d '{"domain":"aere.network","attest":true}'
{ …the report…,
 "attestation":{"reportHash":"0x367a…021d","digest":"sha256 over reportJson, the exact UTF-8 text below","reportJson":"{…}",
  "txHash":"0x0c99…0ef1","block":19018082,"firstSeenAt":1789679286,"firstTime":true,
  "contract":"0x4aB392c4Aca7D9D4C16c0b60a9514c5025bd58c7","chainId":2800,"proof":"/v1/proof/0x367a…021d"}}

The whole perimeter of a domain

POST/v1/pq/readiness/perimeter (keyed)

One hostname says little about a company: the front page is usually behind a modern edge, while the API, the mail gateway and the login host are where classical-only TLS survives. This route measures every public host of a domain in one report: the hosts you name in hosts (labels such as "api", or full names, which must be the domain or under it) plus common prefixes (www, api, app, mail, login, auth, portal, vpn, cdn, admin, secure, shop, status, docs) tried through DNS unless "discover":false. Each host found goes through the same five handshakes as the single scan, at most 16 hosts per report.

$ curl -s https://cloud.aere.network/v1/pq/readiness/perimeter -H "x-api-key: $KEY" -H "content-type: application/json" \
    -d '{"domain":"example.com","hosts":["api","mail"]}'
{"domain":"example.com","generatedAt":"2026-09-18T09:50:00.000Z",
 "summary":{"hostsFound":5,"measured":4,"pending":0,"withoutTls":["mail.example.com"],"failedTransient":0,"notScannedOverLimit":0,
   "withPqKeyExchange":3,"withoutPqKeyExchange":["legacy.example.com"],"tls12Accepted":["legacy.example.com"],
   "worstScore":45,"averageScore":79,"soonestCertificateExpiry":{"host":"api.example.com","daysLeft":9,"validTo":"…"},
   "verdict":"partially prepared: some hosts are exposed to harvest-now-decrypt-later","complete":true},
 "hosts":[{"host":"api.example.com","measured":true,"score":90,"pqKeyExchange":"X25519MLKEM768","tls12Accepted":false,
           "certificate":{"keyType":"EC/prime256v1","issuer":"…","validTo":"…","daysLeft":9},"findings":[],"report":"/v1/pq/readiness/api.example.com"}, …],
 "pending":[],"notFound":[],"refused":[],"discovery":{"tried":13,"wildcardDns":false,"wildcardEchoesDropped":0,"note":"…"}}

It does not invent. The verdict covers measured hosts only and names the exposed ones. A host you named that does not resolve is listed in notFound; a guessed prefix that does not resolve is simply omitted. A host without TLS on port 443 (a mail server, say) is a definitive answer and is listed in withoutTls. In a zone with wildcard DNS every name resolves, so a guessed prefix that resolves to the same addresses as a random name is not evidence of a host: it is dropped and counted in wildcardEchoesDropped; name your real hosts. A host that resolves to an address that is not public is never connected to and appears in refused.

The request has a deadline. A host that swallows connections can hold a scan for most of a minute, so hosts still being measured when the deadline passes are returned in pending with summary.complete:false. Call again: finished scans are cached for six hours and return at once. With "attest":true the digest of a complete report is notarized on chain 2800 exactly like a single scan (an incomplete one answers 409 perimeter_incomplete: an attestation says “this is the measured perimeter”, not “part of it”), and the proof appears in the console beside your other proofs. SDKs 1.3.0: readinessPerimeter(domain, { hosts, discover, attest }), readiness_perimeter(domain, hosts=…, discover=…, attest=…).

Post-quantum adoption by sector

A weekly public series (readable page): what share of the most visited websites, government sites, universities and banks (.bank) negotiate hybrid post-quantum key exchange on their public TLS edge, measured with the same handshakes as the scanner above. Free, no key. GET /v1/pq/adoption returns the latest edition; GET /v1/pq/adoption/YYYY-MM-DD a dated one (404 no_edition if none). Each sector carries its sample rule, the counts selected, measured and not measured (by reason), and every share with numerator, denominator and a Wilson 95% interval; a sector with fewer than 30 measured hosts gets no share. Samples come from the Tranco list named in the edition, so the list can be rebuilt. No host is ever named: the per-host results are kept, and commitment.sha256 commits to them so they cannot be rewritten after publication.

Post-quantum seal record of a block (AIP-21)

GET/v1/pq/finality/{block}?network=testnet|mainnet  ·  GET/v1/pq/finality

Every block is committed with a Falcon-512 seal on each validator’s Commit message; those seals never reach the header (only anchor blocks carry a certificate: every 32nd block, every 128th from block 17,225,968 to block 20,746,736), so until 2026-09-18 they were not observable. This route returns, for one block, the seals a validator heard, re-verified now against the anchored registry over the exact message the validators signed, and the verdict: post-quantum when at least the commit quorum of distinct validators verifies, partial below it, none when nothing verifies, unavailable when nothing was heard (outside the node’s retention window), unverifiable-form when the signed message cannot be rebuilt from the header. What post-quantum proves (corrected 2026-10-01, with the AIP-21 and AIP-22 errata of that date): at least the commit quorum of distinct validators sealed the block post-quantum, in some round. Below block 24,148,751 the seal carried no round, so the verdict was evidence of participation, not by itself proof that the block was decided; from that block, the parent of the first v3 anchor, the record is kept per round and post-quantum means that the quorum of one round verifies; on chain 2800 the classical ECDSA commit quorum of one round sat in the header of a block until block 25,080,000 (2026-10-30); from that block (AIP-22 stage 5) the header carries the Falcon-512 seal of its proposer instead, which admits the header but does not decide the block: the decision is the commit quorum of one round, as before, and its post-quantum proof is the certificate of the next anchor, and a commit still carries the ECDSA commit seal of its validator as an additional check; a node that does not take part in consensus admits a header between anchors on the Falcon-512 seal of its proposer alone, so the post-quantum key of one validator can serve such a node a branch up to the block before the next anchor (below block 25,080,000 that took the ECDSA keys of a quorum), and the next anchor ends it for a node that requires the seals of a quorum in its certificate (the published follower, with its seal ceiling at 1, is not such a node: for it one leaked or misused post-quantum key of a validator makes the rewrite depth unbounded, section 6.4 of the aere-node SPEC). Free, no key. Testnet 28001 first (2026-09-18): the answer comes from a testnet validator through a read-only door that accepts only this method. Chain 2800 since 2026-10-25: ?network=mainnet returns the record of validator 10 (Nethermind-derived) through the read-only door on its own host (client=nethermind, the default and the only client on mainnet for now: the Besu read nodes behind the public RPC also answer aere_getPqFinality, but with unavailable by construction, because commit seals travel only between validators). Since AIP-22 stage R (testnet 28001 from 2026-10-14, chain 2800 from block 24,148,752 on 2026-10-24) each seal is bound to the consensus round and the record reports it (sealForm: anchor-round, decidedRound): a quorum of seals in one round is a decision, not only participation. Verify each seal yourself: signedMessage is what was signed, the public key is the validator’s Falcon-512 key in the published registry epoch for that index.

$ curl -s "https://cloud.aere.network/v1/pq/finality/latest?network=testnet"
{"network":"testnet","chainId":28001,"blockNumber":2245120,"blockHash":"0x…",
 "validators":5,"quorum":4,"sealForm":"anchor","signedMessage":"0x…",
 "falconSealsHeard":4,"falconSealsVerified":4,"verifiedIndexes":[0,1,2,3],
 "falconSeals":[{"scheme":"falcon-512","index":0,"verified":true,"signature":"0x…"}, …],
 "hybridSeals":[], "finality":"post-quantum", "retentionBlocks":256,
 "answeredBy":"validator@8601", "source":"a testnet validator, through the read-only finality door; …", "aip":"AIP-21"}
$ curl -s "https://cloud.aere.network/v1/pq/finality/latest?network=mainnet"
{"network":"mainnet","chainId":2800,"client":"nethermind","blockNumber":24267020,"blockHash":"0x…",
 "validators":10,"quorum":7,"sealForm":"anchor-round","decidedRound":0,"commitRoundBlock":24148752,
 "falconSealsHeard":9,"falconSealsVerified":9,"finality":"post-quantum","answeredBy":"nethermind@8545", …, "aip":"AIP-21"}

Two independent implementations, one verdict (2026-09-18)

Testnet 28001 is validated by two client implementations (Besu-derived and Nethermind-derived), and both implement AIP-21. On chain 2800 the record is served by the Nethermind validator only (no Besu validator of chain 2800 has a public finality door): client=nethermind is the default there, and client=besu and client=both answer a 400 unsupported_client that says so (corrected 2026-10-28: this paragraph named client=both alone and gave client=besu as the default; measured that day). On testnet 28001 client=besu (default) asks a Besu validator, client=nethermind asks the Nethermind validator, and client=both asks each for the same block and reports agreement (the two records carry the same block hash, the same verdict and the same quorum) and postQuantumConfirmedByBoth (both say post-quantum on that hash: the flag to act on). Two clients that both answer unavailable for an old block agree, and the route says unavailable, never a guessed finality. A record that two independently written code bases confirm is a stronger fact than one implementation reporting on itself, and it is the form we recommend for anything you notarize or settle on. What the record proves is said above (corrected 2026-10-01).

$ curl -s "https://cloud.aere.network/v1/pq/finality/latest?network=testnet&client=both"
{"network":"testnet","chainId":28001,"client":"both","blockNumber":2251090,"blockHash":"0x…",
 "finality":"post-quantum","agreement":true,"postQuantumConfirmedByBoth":true,
 "agreementDetail":{"blockHash":true,"finality":true,"quorum":true,"verifiedIndexes":true},
 "besu":{"blockNumber":2251090,"finality":"post-quantum","falconSealsVerified":5,"answeredBy":"validator@8601", …},
 "nethermind":{"blockNumber":2251090,"finality":"post-quantum","falconSealsVerified":5,"answeredBy":"nethermind@8651", …},
 "source":"two independent client implementations …", "aip":"AIP-21"}

Each client keeps only a window of recent blocks (retentionBlocks); a block outside one client’s window returns agreement:false with that client’s record saying unavailable, never a guess. Older blocks are covered by the anchor certificate in the header, which is what /v1/proof reads.

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":"0xfa2375f5c30d25e0b952f5ac07bc292ad3c20433","chainId":2800}

Audit log (2026-09-17)

GET/v1/account/audit?day=YYYY-MM-DD&offset=0&limit=1000

Every keyed request made with your account, with time, method, path and the response status, kept in one append-only file per day (UTC) and served in pages of up to 5,000 entries. The response carries digest, the SHA-256 of the whole day file as served across pages: export it, and if you want the log to be tamper-evident under a post-quantum validator certificate, notarize the digest and keep the proof. A day is capped at 200,000 entries per account; past the cap a single {"truncated":true} line is written and the rest of the day is not journaled. The free health route and the keyless readiness scan are not in the log (they carry no key).

$ curl -s "https://cloud.aere.network/v1/account/audit?day=2026-09-17&limit=3" -H "x-api-key: $KEY"
{"account":"0xbeb3…6465","day":"2026-09-17","total":412,"offset":0,"limit":3,
 "entries":[{"t":"2026-09-17T22:10:03.114Z","m":"GET","p":"/v1/account","s":200},
            {"t":"2026-09-17T22:10:03.401Z","m":"POST","p":"/v1/pq/verify","s":200},
            {"t":"2026-09-17T22:10:04.020Z","m":"GET","p":"/v1/proof/0x367a…021d","s":200}],
 "digest":"0x…","digestOf":"sha256 of the whole day file (one JSON object per line, as served across pages)",
 "maxPerDay":200000, "note":"…"}

The day as a file: format=jsonl and format=cef (2026-09-18)

With format=jsonl the response is the exact bytes of the day file (one JSON object per line). The header x-aere-digest is the SHA-256 of the bytes you received, which is the digest you notarize: checking the log against its proof is one sha256sum, with nothing of ours in between.

$ curl -s "https://cloud.aere.network/v1/account/audit?day=2026-09-17&format=jsonl" -H "x-api-key: $KEY" -D headers.txt -o audit-2026-09-17.jsonl
$ grep -i x-aere-digest headers.txt        # x-aere-digest: 0x5f0c…
$ sha256sum audit-2026-09-17.jsonl          # 5f0c…  the same digest: notarize it, keep the proof

With format=cef the same entries come as ArcSight CEF lines for a SIEM (Splunk, QRadar, Sentinel): CEF:0|Aere Network|Aere Cloud|1|api-ok|GET /v1/account|1|rt=… suser=0x… requestMethod=GET request=/v1/account outcome=200. Severity follows the status class: 1 for 2xx, 5 for 4xx, 6 for 401, 403 and 429, 8 for 5xx. The header still carries x-aere-digest, the digest of the source day file, so an exported day can be tied to its notarized proof. Headers on both: x-aere-day, x-aere-entries; on CEF also x-aere-cef-lines. A day without keyed requests is an empty file, not an error. While a day is still open its file grows, so two downloads can carry two digests, each true of the bytes it came with; notarize closed days. SDKs 1.4.0: auditExport({ day, format }) returns verified (the bytes received hash to the stated digest); Python audit_export(day, fmt) returns the bytes and their SHA-256 computed locally.

Retention of the audit log (2026-09-18)

GET/v1/account/audit/retention with your key, read-only. By default nothing is deleted. You decide how long your audit days are kept, and you set it only with a wallet signature in the console (auditAction: "setRetention" on POST /v1/console/account), never with the API key: a stolen key must not be able to shorten the trail of its own use. POST to the retention route with a key answers 405 read_only_with_api_key.

  • retentionDays: 30 to 3650, or null to keep every day. hold: true stops all deletion (a legal hold).
  • A change that deletes more (fewer days, releasing a hold) takes effect after a 7-day cooling-off, visible as pending with its effectiveAt, and is cancelled by asking again for the value in force. A change that keeps more is immediate.
  • Before a day is deleted, its digest, entry count and size are written to a retention ledger that is never deleted (ledger.entries, with the ledger’s own digest). A deleted day answers 410 audit_day_expired carrying that tombstone, never an empty day: a digest you notarized still verifies the export you kept.

SDKs 1.5: auditRetention(), and auditVerifyKept(day, bytes), which hashes the export you kept locally and compares it with the day we hold or with the tombstone of a deleted day; an error is raised, never returned as “does not match”.

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.

Security command center

The same signed body with "securityAction":"overview" returns the security view the console renders. Read-only, and every number is measured: from the chain, from the readiness scanner, or from your own audit log.

$ curl -s https://cloud.aere.network/v1/console/account   -H "content-type: application/json"   -d '{"address":"0x…","timestamp":1787490000,"signature":"0x…","securityAction":"overview"}'
{"address":"0x…","generatedAt":"2026-09-18T09:05:11.000Z","head":19090832,"passed":3,"failed":3,"unknown":0,
 "checks":[{"id":"api-key-rotated","pass":true,"title":"API key set or rotated in the last 90 days","detail":"25 days (first subscription …)","fix":"…"},
           {"id":"pq-key-exchange","pass":false,"title":"Every monitored hostname negotiates a post-quantum key exchange","detail":"api.example.com","fix":"…"}, …],
 "apiKey":{"known":true,"rotations":0,"lastKeyEvent":"Subscribed","block":15300000,"since":"…","ageDays":25,"basis":"…"},
 "hosts":[{"domain":"www.example.com","score":92,"pqKeyExchange":"X25519MLKEM768","certificate":{"keyType":"EC P-256","issuer":"…","validTo":"…","daysLeft":60},"lastScanAt":1789722300,…}],
 "proofs":{"total":2,"distinct":2,"latest":[{"hash":"0x…","kind":"readiness-attestation","domain":"www.example.com","block":19018082,"txHash":"0x…","finality":"post-quantum","pqAnchor":{"height":19018096,"falconSeals":9,"slhDsaSeals":9},"proof":"/v1/proof/0x…"}]},
 "audit":{"days":[{"day":"2026-09-17","counted":true,"total":7,"ok":4,"clientErrors":2,"serverErrors":1,"digest":"0x…","digestNotarized":true}],"maxPerDay":200000},
 "webhooks":{"total":4,"disabled":1,"max":5}}

Six checks: the API key was set or rotated in the last 90 days; at least one hostname is under continuous quantum-readiness monitoring; every monitored hostname negotiates a post-quantum key exchange; no monitored certificate expires within 14 days; an audit-log day digest of the last 7 days is notarized; no webhook is disarmed. A check is true, false or null: null means it cannot be told from what we hold (no report measured yet, no closed day), and it is counted neither as passed nor as failed. Nothing is scored beyond that.

Proofs. The chain records which digest was notarized and when, not by which customer, so the gateway keeps an address book of what each account notarized through it (POST /v1/notarize, attest:true scans). The address book is a convenience; the finality shown beside each entry is read from the header of the anchor that covers the block, and the proof itself stays on chain 2800, verifiable without us (Proof API). Notarize the digest of a closed audit-log day and that day of your log becomes tamper-evident, against us included: the console shows which days you have closed that way.

Webhooks can be managed with the same signature ("webhookAction":"list" | "create" | "delete", the fields of /v1/webhooks), so an admin adds a hostname to monitor without the production key touching a browser.

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: post-quantum validator ids since block 20,836,228, ECDSA addresses before it (measured 2026-10-01: ten entries).

{"chainId":2800,"count":10,"validators":["0x38fb…49c3","0x5421…cce5", …]}

Post-quantum certified point

GET/v1/data/finality

The parent of the most recent anchor whose post-quantum certificate is present and reaches the threshold in force (AIP-15 / AIP-22): the newest block that at least that many validators sealed post-quantum. Corrected 2026-10-01: this paragraph called it the block a bridge, an exchange or a rollup may treat as final by the chain’s own definition, and said nothing between anchors is final. The certificate’s seals carry no round, so it shows participation, not by itself that the block was decided (AIP-22 erratum of that date); on chain 2800, below AIP-22 stage 5, every block, this one included, is final under the classical ECDSA commit quorum of one round in its header, and between anchors no block carries a post-quantum certificate. (Note added 2026-10-26: from block 24,148,752 the certificate carries the round, and a quorum of one round proves the decision of the parent of its anchor.) (Note added 2026-10-30: from block 25,080,000 headers no longer carry an ECDSA commit quorum; a commit still carries the ECDSA commit seal of its validator as an additional check.) Returned as finalized / safe (the same block, the same hash), with the anchor that covers it, the certificate’s seal counts per scheme, the threshold and lagBlocks behind the head (at most one anchor interval plus one, normally). The certificate is read from the header bytes and counted against the threshold here; its seals are verified cryptographically by the published verifier, which anyone can run. Measured 2026-09-26: on every public node of this chain eth_getBlockByNumber("finalized") and ("safe") answered Unknown block, because QBFT did not set those tags. Measured 2026-10-01: both public endpoints (rpc.aere.network, rpc2.aere.network) answer both tags with the parent of the most recent anchor, the same definition as this route.

$ curl -s "https://cloud.aere.network/v1/data/finality" -H "x-api-key: $KEY"
{"chainId":2800,"head":24545408,"finalized":24545391,"finalizedHash":"0x8612…3641","safe":24545391,"safeHash":"0x8612…3641",
 "anchor":24545392,"anchorHash":"0xd726…a372","threshold":7,"lagBlocks":17,
 "certificate":{"version":3,"form":"v3","round":0,"falconSeals":9,"slhDsaSeals":9,"signers":9,"falconSigners":9,"digest":"0xbacf…8565"},
 "quorumByIndices":true,"quorumRound":0,"quorum":7,"parentSetSize":10,"commitRoundBlock":24148752,
 "verified":"presence-and-threshold","note":"finalized = the parent of the most recent anchor …"}

The answer above was produced on 2026-10-27 by the code of this route reading the public chain, at head 24,545,408; until that date this example showed an older answer, at head 20,266,956, before AIP-22 stage R (threshold 6, certificate version 2, without form, round, falconSigners and the quorum fields).

Errors: 503 no_certified_anchor when none of the recent anchor heights carries a certificate reaching the threshold (never happened on the live chain; stated so a partial answer never looks complete), and 503 threshold_unmeasured when the threshold in force could not be established on this server, so that no anchor is counted; that says nothing about the chain. Both carry finalized: null. (The second error was returned since 2026-10-09 and is documented here since 2026-10-27.)

Post-quantum anchors

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

Anchor blocks of chain 2800 carry the validators’ post-quantum certificate: its 32-byte digest sits in the first bytes of extraData, under the block hash, and the seals themselves ride alongside (a v2, scheme-tagged certificate from 2026-09-04, with Falcon-512 seals and, at every anchor until 2026-09-29 and at every 128th block since, SLH-DSA-128s seals, not always from every Falcon-512 signer (measured 2026-10-27: 8 Falcon-512 and 6 SLH-DSA seals at block 17,047,600; the anchor at block 17,102,384, under a one-anchor step of the minimum to zero, carries Falcon-512 seals only; corrected 2026-10-27: this said from each signer); since block 24,148,752 (AIP-22 stage R) a v3 certificate, which also names the consensus round of its seals). The grid is a consensus parameter with dated steps, returned as anchorSchedule: heights 13,014,000 + k·32 until block 17,225,968, then 17,225,968 + k·128 (2026-09-05), then 20,746,736 + k·32 again (since 2026-09-29). anchored is measured from the header bytes, never assumed from the height. This endpoint parses that structure for you.

$ curl -s "https://cloud.aere.network/v1/data/anchors?limit=2" -H "x-api-key: $KEY"
{"chainId":2800,"head":24493016,"anchorIntervalBlocks":32,"firstAnchorBlock":13014000,
 "anchorSchedule":[{"fromBlock":13014000,"intervalBlocks":32,"since":"2026-08-09"},
                   {"fromBlock":17225968,"intervalBlocks":128,"since":"2026-09-05"},
                   {"fromBlock":20746736,"intervalBlocks":32,"since":"2026-09-29"}],
 "universalSince":13889296,
 "note":"anchor heights: …",
 "anchors":[
  {"height":24493008,"hash":"0x85c1…0623","timestamp":1793027801,"anchored":true,
   "certificateVersion":3,"certificateForm":"v3","certificateRound":0,"certificateWellFormed":true,
   "falconSeals":10,"slhDsaSeals":0,"signers":10,"falconSigners":10,"seals":10,
   "certificateDigest":"0x121b…fc2c","validatorsListed":10},
  {"height":24492976,"hash":"0x0dc4…dccd","timestamp":1793027772,"anchored":true,
   "certificateVersion":3,"certificateForm":"v3","certificateRound":0,"certificateWellFormed":true,
   "falconSeals":10,"slhDsaSeals":0,"signers":10,"falconSigners":10,"seals":10,
   "certificateDigest":"0x2a6f…37a3","validatorsListed":10}]}

The answer above was read on 2026-10-26 at head 24,493,016; until that date this example showed an answer of 2026-09-17, at head 19,018,276, before stage R (certificate version 2, interval 128, two schedule steps). certificateForm is v1, v2, v3, none or unknown (a form that no client accepts; until 2026-10-26 that value was sent as necunoscuta). falconSeals counts the Falcon-512 rows carried and falconSigners the distinct validator indices among them, equal on a well-formed certificate; validatorsListed is the size of the validator set the header lists.

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 20,715,632 (2026-09-29) an anchor does not finalize with fewer than seven valid seals, as many as the quorum of the ten validators (six from block 14,961,456: six of the nine validators of that time, then below the quorum of seven from 2026-09-11); below block 24,148,752 the seals proved those validators signed the block, not that it was decided (AIP-22 erratum, 2026-10-01), and from that block a certificate that carries the quorum of one round proves the decision; the counts you see here are the chain’s own, typically 8 to 10.

Webhooks

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

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

typefirespayload data
pq-anchorsevery new post-quantum anchor (every 32 blocks, roughly every 20 seconds; every 128 from block 17,225,968 to block 20,746,736)the Anchor object of /v1/data/anchors: height, hash, timestamp, anchored, certificateVersion, certificateForm, certificateRound, certificateWellFormed, falconSeals, slhDsaSeals, signers, falconSigners, seals, certificateDigest, validatorsListed
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)
quantum-readinesscontinuous monitoring of one hostname (2026-09-17): the readiness scan is repeated every six hours; the first report is delivered as a baseline, then only changes (post-quantum key exchange appearing or disappearing, preference, TLS 1.2, HSTS, findings, certificate expiry crossing 30 / 14 / 7 / 1 days) or a measurement errordomain, changed[], report (score, verdict, summary, certificate expiry step, finding ids), previous, measuredAt, reportUrl
quantum-perimetercontinuous monitoring of every public host of a domain (2026-09-18): the perimeter scan is repeated every 6 hours with the same domain, hosts and discover you give at creation. The first delivery is the baseline; after that you are called only when something changes: a host appeared or disappeared, a host gained or lost post-quantum key exchange, TLS 1.2 acceptance changed, or a certificate crossed an expiry step (30, 14, 7, 1 days). Each change names the host, with from and to. An incomplete measurement is never judged or delivered; it is retried five minutes later.

Create with {"type":"quantum-readiness","url":"…","domain":"example.com"}; the listing shows lastScanAt, lastScore, lastChangeAt per watched domain.

$ 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 (every 128th from block 17,225,968 to block 20,746,736, 2026-09-05 to 2026-09-29) 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.

Proof API: a digest under a post-quantum certificate

GET/v1/proof/{hash}

A timestamp is only as strong as the chain under it. For any notarized digest this endpoint returns the block and transaction of its first appearance (read from the contract’s own event log, not from our memory), the post-quantum anchor that covers it (the first anchor block at or after that height, read from its header: certificate version, Falcon-512 and SLH-DSA-128s seal counts, distinct signers, certificate digest), a finality verdict, and verify: how to check every claim on any chain-2800 node and with the public anchor verifier, without us. finality is post-quantum once the covering anchor exists and carries a certificate (the value names the certificate, not a decision: since the AIP-22 erratum of 2026-10-01 a certificate is read as evidence that its signers sealed the chain at that height), pending until then (with pqAnchorExpectedAt), and first-seen-only if the first appearance could not be located in the log. Unknown digests answer 404 with notarized:false. Counted as one data request.

$ curl -s https://cloud.aere.network/v1/proof/0x367a1967df839dab40e2a62e053a38950e759f90b26aa87a259d38cb784e021d -H "x-api-key: $KEY"
{"hash":"0x367a…021d","notarized":true,
 "firstSeenAt":1789679286,"firstSeenIso":"2026-09-17T21:08:06.000Z",
 "block":19018082,"blockHash":"0xc5fb…cba9","txHash":"0x0c99…0ef1",
 "confirmations":194,"head":19018276,
 "finality":"post-quantum",
 "pqAnchor":{"height":19018096,"hash":"0xf776…b3f1","timestamp":1789679295,"anchored":true,
   "certificateVersion":2,"falconSeals":9,"slhDsaSeals":9,"signers":9,"seals":18,
   "certificateDigest":"0x19c4…f870"},
 "pqAnchorsSince":2,
 "contract":"0x4aB392c4Aca7D9D4C16c0b60a9514c5025bd58c7","chainId":2800,
 "verify":{"firstSeenAt":"eth_call to the contract with proofOf(bytes32) on any chain-2800 node …",
   "firstAppearance":"eth_getLogs address …, topics [Notarized, hash] at block 19018082",
   "pqAnchor":"the header of block 19018096 carries the validators' post-quantum certificate under its hash; verify it without us: https://aere.network/tools/verify-anchor.mjs",
   "meaning":"after the anchor, rewriting the block that holds this proof would require post-quantum validator signatures, not only classical ECDSA keys (one exception, named in the AIP-22 erratum of 2026-10-01: when this block is the anchor's parent, an anchor below the commit-round height can also be certified, with honest validators' seals, over its undecided sibling; measured in a test fixture, not exercised on any network)"}}

What it means, plainly: a classical timestamping service proves order with ECDSA-signed blocks, and a future quantum adversary who recovers those keys could rewrite the history under the proof. Here, once the covering anchor exists, rewriting that history would also require forging a Falcon-512 certificate of the validator set (with one exception, named in the AIP-22 erratum of 2026-10-01: when the block is the anchor’s parent, honest validators’ seals can also certify an anchor below block 24,148,752 over its undecided sibling; measured in a test fixture, not exercised on any network; from that block a certificate whose quorum is of one round closes it) and, once the next 128th-block anchor exists, one that adds SLH-DSA-SHA2-128s seals: two NIST post-quantum schemes. GET /v1/notarize/{hash} now returns proof, the path to this record.

Verify any AERE proof: Trust API

POST/v1/verify  ·  optional ?chain=2800|28001

Send one envelope of the AERE Proof Protocol (AIP-23), of any kind (data, execution, identity, compliance, runtime, location, device, payment, ownership, time, block, authorization, settlement, provenance, AI, software), and get one verdict back: VALID, INVALID or PARTIAL, with every level that was checked. The judgment is not a second implementation: the gateway runs the published reference verifier, verify-proof.mjs, unmodified, on your envelope, and the answer carries that file’s SHA-256 and the command that reproduces the verdict on your own machine, without us.

$ curl -s https://cloud.aere.network/v1/verify -H "x-api-key: $KEY" -H "content-type: application/json" -d @payment.json
{"verdict":"VALID",
 "statementHash":"0x0e937d67740e2314dfa003848dc46600bf6086d3449097f5eb222665c75a4e32",
 "levels":[
  {"level":"form","state":"PASSED","detail":"kind=aere-proof-of-payment-attestation"},
  {"level":"integrity","state":"PASSED","detail":"sha256(statement) == statementHash (0x0e937d67740e2314..)"},
  {"level":"signature","state":"ABSENT","detail":"the envelope carries no signature"},
  {"level":"finality","state":"ABSENT","detail":"no notarization claimed and no --rpc given"}],
 "verifier":{"file":"verify-proof.mjs","sha256":"…",
   "url":"https://aere.network/tools/verify-proof.mjs"},
 "reproduce":"node verify-proof.mjs envelope.json --json"}

The levels, in order: form (a statement and a statementHash); integrity (SHA-256 of the canonical statement equals statementHash: change one field and it is FAILED); signature (an ML-DSA signature over the statement, when the envelope carries one); finality (when the envelope claims a notarization: the chain’s most recent post-quantum anchor is verified seal by seal against the published key manifests, and a Merkle proof under that certified block shows the notary contract holds the digest and when it was first seen). A level the envelope does not carry is ABSENT, never counted as passed. The verdict: INVALID if a level present failed, PARTIAL if a level present could not be measured, VALID if every level present passed. So a bare, unsigned envelope is VALID as to its integrity only: read the levels, not just the verdict.

What it does not decide: whether a statement is true in the world. An envelope says what is claimed and who signed it; the truth of a “location” or a “device” depends on who attests it. Limits: one envelope per request, at most 64 KB; chain selects the network whose notary and anchors are read (by default, the one the envelope’s notarization declares, else 2800). A verification with finality reads the chain and takes seconds, not milliseconds. Errors: 400 bad_envelope or unknown_chain, 413 envelope_too_large, 429 busy or busy_account with Retry-After (verifications in flight are capped overall and per account), 502 verifier_inconsistent when the verifier’s verdict and exit code disagree (never passed on as a verdict), 504 verifier_timeout (not INVALID). Counted as one verify request in your account usage.

Verify an identity presentation

POST/v1/identity/verify

Checks a presentation of an AERE Identity credential: a credential its issuer signed with a hybrid signature (Ed25519 and ML-DSA-65, both required), bound to its holder’s keys, of which the holder showed only the claims they chose (selective disclosure), made for your verifier (your audience and your nonce), optionally presented through a chain of delegations that can only narrow, and revocable through the issuer’s status list. As with the Trust API, the judgment is not a second implementation: the gateway runs the published command line, identity-cli.mjs verify, on your request, and the answer carries the SHA-256 of the files that judged and the command that reproduces the verdict without us.

$ curl -s https://cloud.aere.network/v1/identity/verify -H "x-api-key: $KEY" -H "content-type: application/json" -d '{"presentation":{…},"audience":"https://your.app/verifier","nonce":"c-7f3a","trustedIssuers":["aere-id:…"],"statusLists":[{…}]}'
{"verdict":"VALID","notJudged":0,
 "subject":{"type":"KycCredential","credential":"urn:uuid:…","issuer":"aere-id:…",
   "holder":"aere-id:…","presenter":"aere-id:…","delegations":0},
 "claims":{"age_over_18":true,"jurisdiction":"RO","kyc_level":2},
 "rows":[{"name":"credential: signed by aere-id:… (Ed25519 and ML-DSA-65, both)","pass":true,"detail":""},…],
 "judgedAt":"2026-09-30T…Z",
 "verifier":{"tool":"identity-cli.mjs verify","sha256":{"identity.mjs":"…",…},"source":"https://git.aere.network/aere-network/aere-quantum/src/branch/main/identity"},
 "reproduce":"node identity/identity-cli.mjs verify --presentation presentation.json --audience <audience> --nonce <nonce> … --at 2026-09-30T…Z --json"}

Required: presentation (the file identity-cli.mjs present writes), audience and nonce, your verifier’s identifier and the challenge you gave the holder: without them a presentation made for someone else would pass, so the route does not run without them (URI characters, up to 256). Optional: trustedIssuers (issuer ids or public keys, up to 32), statusLists (the issuers’ current lists, up to 8), revocations (revocations of delegations, up to 32), maxAgeSeconds (1 to 3600, default 300: how far the presentation’s time may be from ours). Clocks differ: a credential or status list that starts up to 60 seconds in our future is accepted, and a revocation dated up to 60 seconds ahead already counts; an end date gets no allowance. The verdict: INVALID if a row failed; PARTIAL if every row that could be judged held but some could not be judged (no trusted issuers given, the issuer’s status list not handed over, a delegation without its revocations), and those rows say so with pass: null; VALID only if everything was judged and held: read verdict, since a PARTIAL presentation may carry claims that anyone could have signed with their own keys. claims and subject are returned only when no row failed. The reproduce command carries the moment of the judgment (--at), so run later on the same files it gives the same verdict, and for a compliance check the same record, byte for byte.

Verify a standard SD-JWT

POST/v1/identity/sd-jwt/verify

The same verification for credentials in the IETF standard format, Selective Disclosure for JSON Web Tokens (RFC 9901): an SD-JWT with a Key Binding JWT, in compact serialization. You give the issuer’s public key (a JWK, or the public keys of an AERE identity), and the answer follows the verification steps of RFC 9901 sections 7.1 and 7.3: the issuer signature with that key and no other, every disclosure bound to a digest, no digest twice, the key binding signed by the holder key named in the token, for your audience and your nonce, recent, and over exactly what was presented. Algorithms: ES256, EdDSA (Ed25519) and ML-DSA-65 (JOSE name from RFC 9964). With the public keys of an AERE identity (Ed25519 and ML-DSA-65), the ML-DSA-65 half is judged; the Ed25519 half is judged only when you ask with "classicalHalf": true, and the answer then says "postQuantum": false (since 2026-10-19: until then this route judged the Ed25519 half by default, so a token signed with the classical key alone passed against the whole identity). A plain JWK is judged with that key, as before. Judged by identity-cli.mjs verify-sdjwt from the same repository, checked there against the RFC’s own example vectors and, on 2026-10-18, against an independent open-source SD-JWT implementation in both directions.

$ curl -s https://cloud.aere.network/v1/identity/sd-jwt/verify -H "x-api-key: $KEY" -H "content-type: application/json" -d '{"sdJwt":"eyJ…~WyJ…~eyJ…","issuerKey":{"kty":"OKP","crv":"Ed25519","x":"…"},"issuerAlg":"EdDSA","audience":"https://your.app/verifier","nonce":"c-7f3a","expectedIssuer":"https://issuer.example"}'
{"verdict":"VALID","reason":"","payload":{"iss":"https://issuer.example","exp":…,"age_over_18":true,…},
 "disclosed":["age_over_18"],"issuer":"https://issuer.example","issuerChecked":true,
 "keyBinding":{"aud":"https://your.app/verifier","nonce":"c-7f3a","iat":…,"alg":"EdDSA"},"alg":"EdDSA","postQuantum":false,…}

Required: sdJwt, issuerKey, audience and nonce. Optional: issuerAlg (default: ML-DSA-65 for the keys of an AERE identity, the algorithm of the key for a plain JWK), classicalHalf (true lets the Ed25519 half of an AERE identity be judged), expectedIssuer (the iss you expect; without it issuerChecked is false), maxAgeSeconds for the key binding (1 to 3600, default 300). The token must carry exp and be explicitly typed (…+sd-jwt). postQuantum is true only when every signature judged (the issuer’s and the key binding’s) is ML-DSA-65. INVALID comes with its reason; payload is the processed payload of RFC 9901 (the claims in the clear plus those disclosed) and only for a valid token. Counted as an identity request; the same errors as the identity route.

Check a compliance policy

POST/v1/compliance/check

Your compliance policy (which issuers you trust, which claims you require: over 18, a jurisdiction outside a list, a verification level of at least 2) judged on a presentation, with the same checks as above; the trusted issuers are those of the policy, under its hash. The answer is COMPLIANT or NOT_COMPLIANT with the reasons, the policy’s hash and the presentation’s digest, and none of the claims. With "record": true it also returns the record of the decision as an AIP-23 compliance envelope that carries no personal data: a pseudonym of the holder bound to your audience, the policy hash, the result and the digest of the presentation’s signed binding (it names the credential, the disclosures, the delegations, your audience, your nonce and the time). Keep it, or notarize it with /v1/notarize so that the chain fixes the moment; the Trust API verifies it. The pseudonym is a hash of the holder id and your audience, which anyone who knows both can recompute; the command line can key it with a secret of yours, which this route does not take.

$ curl -s https://cloud.aere.network/v1/compliance/check -H "x-api-key: $KEY" -H "content-type: application/json" -d '{"presentation":{…},"audience":"https://your.app/verifier","nonce":"c-7f3a","statusLists":[{…}],"record":true,"policy":{"id":"onboarding-v1","trustedIssuers":["aere-id:…"],"require":[{"claim":"age_over_18","equals":true},{"claim":"jurisdiction","notIn":["KP","IR"]},{"claim":"kyc_level","atLeast":2}]}}'
{"verdict":"COMPLIANT","compliant":true,"reasons":[],"policyId":"onboarding-v1","policyHash":"0x…",
 "presentationHash":"0x…","notJudged":0,
 "record":{"v":1,"kind":"aere-proof-of-compliance-attestation","statement":{…},"statementHash":"0x…"},…}

Rules: equals, in, notIn, atLeast, present; unknown fields are refused, in the policy and in the request. A policy requires the credential’s status to be judged unless it says "requireStatus": false: a status list not handed over is “not judged”, never “not revoked”. What neither route is: a zero-knowledge proof (a disclosed claim is shown whole; “over 18” is a claim the issuer made, not a computation over a birth date nobody saw), an AML or sanctions screening (no list is consulted), or a statement that anyone complies with a law: it says that one presentation met one policy at one moment, judged by you. Errors (both routes): 400 bad_request, unknown_field or rejected_input (the tool’s own reason, for a broken policy or issuer key), 413 body_too_large (256 KB), 429 busy or busy_account (verifications in flight are capped overall and per account; the caps are shared with /v1/verify), 400 too_deep (JSON nested beyond 64 levels), 502 verifier_inconsistent or verifier_no_verdict, 504 verifier_timeout. Counted as identity and compliance requests in your account usage. The claims a holder disclosed reach us in the request: see data handling.

Payments: the risk step

POST/v1/payments/risk

One payment by a person or a company, judged under your declared policy by the published module payments: a limit per payment and a sliding-window limit in USD per payer, the assets you allow, the counterparties you refuse (each with its source). The answer is one verdict, ALLOW or REFUSE, with the reasons, what was measured, and what was not: the signals this API does not have are named in unmeasured in every verdict and never simulated (no sanctions list is consulted, no identity tier, no device or location, no chargeback history, nothing about the payer outside the history you send). The verdict's hash covers the policy's hash and the inputs' hash, so anyone with the same policy and inputs reproduces it. Prices are in USD at the rate you declare in the inputs, with its source and time; it is not a market price, and without it the request is refused, not guessed. A refusal is a verdict (HTTP 200), not an error.

$ curl -s https://cloud.aere.network/v1/payments/risk -H "x-api-key: $KEY" -H "content-type: application/json" -d '{"policy":{"v":1,"kind":"aere-payment-risk-policy","id":"shop-v1","currency":"USD","perPaymentMaxUsd":"100.00","window":{"seconds":86400,"maxUsd":"250.00","maxCount":5},"allowedAssets":[{"chainId":2800,"asset":"native","decimals":18}],"refusedCounterparties":[]},"inputs":{"chainId":2800,"payer":"0x…","payee":"0x…","asset":"native","amount":"400000000000000000","rate":{"usdPerUnit":"0.5","source":"your price source","at":"2026-10-03T08:00:00Z"},"history":[],"now":1791000000}}'
{"verdict":"ALLOW","reasons":[],"measured":{"amountUsd":"0.200000","windowUsd":"0.000000","windowCount":0,…},
 "unmeasured":["sanctions screening: no source consulted","identity or verification tier of the payer: none",…],
 "policyHash":"0x…","inputsHash":"0x…","verdictHash":"0x…",
 "verifier":{"module":"payments","sha256":{"risc.mjs":"…","chitanta.mjs":"…"},"source":"https://git.aere.network/aere-network/aere-quantum/src/branch/main/payments"},…}

Unknown fields are refused, in the policy and in the request: nothing this API ignores can be shown to a reader as applied, and no host can be named by the caller.

Payments: the receipt

POST/v1/payments/receipt

For a payment already on chain: you send the same policy and inputs and the transaction hash. The verdict is reproduced and must be ALLOW (otherwise 409 risk_refused, with the reasons); the transaction is read from the chain and must be the payment judged: from the payer, to the payee, for the amount, mined (otherwise 404 tx_not_found or 409 tx_mismatch). The receipt is an instruction (payer, payee, the amount in the asset and in USD at the declared rate, the transaction, the verdict with its policy under hash, the unmeasured signals) and an AIP-23 settlement envelope that commits to it by hash; the envelope is notarized, so the receipt's time is the chain's. If the notarization fails the answer is 502 notarization_failed with the receipt built: a receipt never claims a time it does not have. The answer also carries receiptFile: the receipt with the policy and the inputs you sent, which is the file the public reader takes; save it as receipt.json (corrected 2026-10-27: until this date the answer carried only receipt, and the reader cannot judge the risk verdict without the policy and the inputs). Native-asset payments only.

$ curl -s https://cloud.aere.network/v1/payments/receipt -H "x-api-key: $KEY" -H "content-type: application/json" -d '{"policy":{…},"inputs":{…},"txHash":"0x…","purpose":"order 1042"}'
{"receipt":{"instruction":{"kind":"aere-payment-receipt-instruction","payer":"0x…","payee":"0x…","amount":"400000000000000000","amountUsd":"0.200000",
   "rate":{"usdPerUnit":"0.5","source":"your price source","at":"…"},"txHash":"0x…","risk":{"decision":"ALLOW","policyHash":"0x…","verdictHash":"0x…",…},…},
  "envelope":{"kind":"aere-proof-of-settlement-attestation","statement":{…},"statementHash":"0x…","notarization":{"chainId":2800,"firstSeen":…,"txHash":"0x…"}}},…}

Payments: verify a receipt

POST/v1/payments/verify

A receipt checked from the outside: the envelope commits to the instruction, the USD amount is exactly amount times the declared rate, the policy shown hashes to the one under the verdict, the verdict reproduces from the inputs and was ALLOW, the transaction on chain is this payment, and the envelope's notarization is read under a post-quantum certified anchor by the reference verifier. VALID, INVALID with the reasons, or PARTIAL when something was not measured: the notarization not under an anchor yet, the reference verifier or this gateway’s node not answering. You do not need this API for it: with receipt.json = the receiptFile of the receipt route (or { ...receipt, policy, inputs }), node payments/verifica-chitanta.mjs receipt.json --rpc <your RPC> --verify-proof verify-proof.mjs gives the same verdict from your own machine, with verify-proof.mjs as served at aere.network/tools and verify-anchor.mjs, mpt.mjs, falcon512.mjs, registry-v3.mjs and package.json from the same place beside it, with npm install done there (the verifier alone stops at its first import, and the reader then says PARTIAL; corrected 2026-10-27: this sentence did not name those files): exit 0 VALID only with the notarization’s finality PASSED, 1 INVALID, 2 PARTIAL. (Corrected 2026-10-27: until this date the reader wrote VALID without --verify-proof and while the notarization was pending, where this route answers PARTIAL, and a node that did not answer made this route say INVALID.)

What this is not: a payment processor (it moves no money; the payer pays with its own signature), KYC, AML or sanctions screening (no list is consulted, and every verdict says so), or a judgement that your policy is a good one. The notary is one key, the gateway's; the rate is the one you declare.

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.

Data handling

Written for procurement, and true as of 2026-09-17, amended 2026-09-30 for the identity routes. What we receive: 32-byte digests (notarization, Proof API), public keys, signatures and messages you choose to verify (post-quantum verification), hostnames (readiness scans, monitors), addresses you choose to watch, webhook URLs, and the JSON-RPC calls you route through your key. What we never receive: your documents, your private keys, your users’ keys (accounts created through gas sponsorship are smart accounts owned by your users), or the reports of readiness scans you did not ask us to attest. Hybrid signing (@aere/pq-sign) and Proof of Software run entirely on your side; only digests reach us, and only if you send them. One exception, since 2026-09-30: the identity and compliance routes receive the presentation you send, with the claims its holder chose to disclose. The gateway uses them to answer and keeps none of them: they are written only to a temporary directory deleted when the answer is sent, and neither the audit log (time, method, route and status of each request) nor the usage counters hold them. If disclosed claims must not leave your systems, run the same command line yourself: the verdict is the same. What we keep: per-account usage counters (31 days, for billing and /v1/account), the per-account audit log (append-only day files; export it with /v1/account/audit), webhook definitions and delivery state, cached readiness reports (six hours), the last readiness fingerprint per monitored hostname. Everything written to chain 2800 (notarized digests, attested report digests, subscriptions) is public and permanent by design. Where: all processing and storage is in the European Union. Encryption we cannot undo: there is nothing to decrypt, because nothing sensitive is sent (the identity routes aside, whose claims are not stored); that is the design, not a policy. Formal certifications (SOC 2, ISO 27001) are on the roadmap; until then every claim on this page is measurable from the public endpoints that make it.

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-10-27: the OpenAPI document (1.9.0) describes the answer of /v1/pq/finality as the gateway gives it since AIP-22 stage R: sealForm anchor-round, client, commitRoundBlock, decidedRound, recordRound, rounds and the round of each seal; until this date its schema named only anchor and commit-digest, so a client generated strictly from it refused the answer. This page names every route that takes no key (it named /v1/health alone), and a refused key is told to register through AereCloudSubscriptionsV2.subscribe, the contract at the address it names (the gateway said AereCloudSubscriptions).
  • 2026-10-27: the first step of anchorSchedule (/v1/data/anchors) says since 2026-08-09, the day of block 13,014,000; until this date it said 2026-08-05, four days before its block, and the anchors example of 2026-10-26 showed that value. The rules of the Payments API verdict are named in English (form, asset, counterparty, rate, limit, window); until this date the API returned the names of the published module (forma, activ, contrapartida, curs, limita, fereastra), which still uses them, and verdictHash is unchanged because rules sits outside the hashed body. The /v1/data/finality example is an answer of this date and the error threshold_unmeasured is documented; the OpenAPI summary of /v1/health no longer calls it the only route without a key.
  • 2026-10-26: certificateForm (/v1/data/anchors, the pq-anchors webhook, and certificate.form of /v1/data/finality) names a certificate form that no client accepts unknown; until this date it was sent as necunoscuta, a word of our working language. The OpenAPI document gives the field its enum (v1, v2, v3, none, unknown), documents falconSigners and validatorsListed of the Anchor object and the fields /v1/data/finality returns since AIP-22 stage R, and its anchors example is an answer of 2026-10-26.
  • 2026-10-19: SD-JWT verification of an AERE identity judges its ML-DSA-65 half by default; the Ed25519 half only with "classicalHalf": true, and every answer says postQuantum. A token an AERE identity signed with its Ed25519 key alone now needs classicalHalf; plain JWKs are unchanged.
  • 2026-09-30: identity and compliance verification (POST /v1/identity/verify, POST /v1/compliance/check): AERE Identity presentations judged by the published command line, VALID / PARTIAL / INVALID and COMPLIANT / NOT_COMPLIANT, and standard SD-JWT (RFC 9901) with key binding (POST /v1/identity/sd-jwt/verify), with the record of a compliance decision as an AIP-23 envelope without personal data. Account usage now reports the identity and compliance families. OpenAPI 1.7.0. The official clients 1.7.0 carry them in all five languages (identityVerify / complianceCheck; in Go the presentation travels as its bytes, so large numbers stay exact).
  • 2026-09-29: Trust API (POST /v1/verify): one AIP-23 proof envelope of any kind in, VALID / INVALID / PARTIAL out, with each level checked, judged by the published reference verifier and reproducible without us. Account usage now reports the verify family. OpenAPI 1.6.0. The official clients 1.6.0 carry it in JavaScript, Python, Go and Java, plus a new .NET client; in Go the envelope is passed as its bytes, since a map would reorder the statement's keys and change its hash.
  • 2026-09-26: the post-quantum finality point of the chain (GET /v1/data/finality): finalized and safe as the parent of the most recent anchor whose certificate is present and reaches the threshold in force, with the anchor, the certificate’s seal counts and the lag behind the head. Measured the same day: eth_getBlockByNumber("finalized") answers Unknown block on every public node of chain 2800, because the consensus does not set the tag; this route is the reference until the nodes expose it themselves. SDKs 1.5.2 (finality() in JavaScript, Python, Go, Java), OpenAPI 1.5.2.
  • 2026-09-22: post-quantum adoption by sector, a weekly public series (GET /v1/pq/adoption, no key): sector aggregates only, each share with its 95% interval, per-host results committed by SHA-256 and never published. The console's security view now saves as a PDF report, including the hosts of a monitored perimeter. OpenAPI 1.5.0.
  • 2026-09-25: the official clients in four languages (JavaScript, Python, Go, Java), installed from the repository because they are not on npm or PyPI yet (the page said npm install of a name that did not exist there); none of them follows redirects. The retention of the audit log, live since 2026-09-18, is now documented.
  • 2026-09-18: the audit log of a day as a file: format=jsonl returns the exact bytes whose SHA-256 is the digest you notarize (one sha256sum verifies it), format=cef returns CEF lines for a SIEM; SDKs 1.4.0.
  • 2026-09-18: webhook type quantum-perimeter: the whole perimeter of a domain under continuous monitoring, changes only, each naming the host; its hosts appear in the console’s security view.
  • 2026-09-18: The whole perimeter of a domain in one keyed report (POST /v1/pq/readiness/perimeter): named hosts plus common prefixes found through DNS, a summary derived from measured hosts only, wildcard-DNS echoes dropped, a request deadline with pending, and attest for complete reports; SDKs 1.3.0. The readiness scanner and webhook delivery now refuse any hostname that resolves to an address that is not public, and connect to the verified address.
  • 2026-09-18: Security command center in the console, behind the wallet signature: six measured checks (API key age, monitored hostnames, post-quantum key exchange, certificate expiry, notarized audit-log days, disarmed webhooks), the proofs your account notarized with their finality read from the chain, and the audit log of the last 7 days with each day’s digest. Webhooks of type quantum-readiness can now be created from the console too.
  • 2026-09-18: Post-quantum finality of a block (AIP-21) served by two independent client implementations: client=besu|nethermind|both, with agreement and postQuantumConfirmedByBoth computed by the gateway on the same block; SDKs 1.2.1 (pqFinality(block, network, client)).
  • 2026-09-17: Quantum readiness scan (free, keyless; keyed attest notarizes the report digest on chain), Proof API (GET /v1/proof/{hash}: first appearance from the contract log, the covering post-quantum anchor, a finality verdict and independent verification steps), and a correction to the anchor endpoints: since the anchor interval moved to 128 blocks on 2026-09-05, /v1/data/anchors and the pq-anchors webhook had kept the old 32-block grid, so three of every four heights they reported were not anchors; both now follow the dated anchorSchedule, report anchored from the header bytes, and count the hybrid v2 certificate’s seals per scheme (falconSeals, slhDsaSeals, signers) instead of the previous wrong count. OpenAPI 1.1.0.
  • 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].

Aere Cloud: overview · API docs · console · status