Skip to main content

Overview

To use the Herodotus Cloud Services APIs, you need to obtain an API key:
  1. Visit the Herodotus Console.
  2. Register or log in using your GitHub account or in-browser wallet with Sign in with Ethereum.
Herodotus Console Login
  1. Apply for credits or use an invite link to a project with credits.
Herodotus Console Project
  1. Once logged in, you can access your API key for your Project.
Herodotus Console API Keys
  1. Include this API key in your requests to authenticate with the API.

Programmatic wallet authentication

For AI agents, CLIs, and other non-browser clients, you can authenticate without the Herodotus Console UI using an EVM wallet and the EIP-712 challenge flow. The result is a Bearer access token plus an API key — no cookie jar required.
Want a copy-paste playbook for an AI assistant? Load the Herodotus Auth AI Skill — it includes the full protocol contract, anti-hallucination guardrails, and a viem reference example.
Base URL (prod): https://auth-billing.api.herodotus.cloud

Step 1 — Fetch a challenge

Response contains a short-lived challengeToken plus an eip712 object with domain, types, primaryType, and message. Sign exactly those fields — do not reconstruct them client-side.

Step 2 — Sign the typed data

Use any EIP-712 signer (viem, ethers, MetaMask, KMS, hardware wallet). The wallet that signs must match the address in the challenge URL.

Step 3 — Exchange for a Bearer session

Response body:
When channel is "bearer", no Set-Cookie is sent. Use Authorization: Bearer <accessToken> on every subsequent call. Omit channel (or pass "cookie") to fall back to the browser cookie flow.

Step 4 — Retrieve your API key

First-time wallets are auto-provisioned with a Personal project and one active API key. Read it with:
Response data[0].apiKey is the value to use against Atlantic API, Storage Proof API, etc. To mint additional keys later, POST /api-keys with { "projectId": "...", "type": { "name": "...", "color": "..." } }.

Step 5 — Refresh

When the access token approaches expiresAt, exchange the refresh token for a new pair:
Response body returns a fresh { accessToken, refreshToken, expiresAt }. The previous refresh token is invalidated. Cookie callers continue to refresh via cookies — the same endpoint serves both transports.
Channel binding is enforced server-side. A token issued with channel: "bearer" is rejected if presented via cookie, and vice versa. This is a security property — do not extract a cookie session JWT and forward it as Authorization: Bearer. If you need both surfaces, run the cookie path and the bearer path independently.

End-to-end example (viem)