| title | description |
|---|---|
Authentication |
Learn how to authenticate with elizaOS Cloud APIs using API keys, session tokens, wallet signatures (SIWE and per-request), and x402 payments. |
import { Callout, Tabs, Cards } from "nextra/components";
Secure your API requests with elizaOS Cloud authentication methods.
elizaOS Cloud supports multiple authentication methods:
| Method | Use Case | Header / flow |
|---|---|---|
| API Key | Server-to-server | Authorization: Bearer eliza_xxx or X-API-Key |
| Session | Browser apps | Cookie-based (Privy) |
| SIWE | Wallet sign-in, get API key | GET nonce → sign message → POST verify → use key |
| Wallet header | Per-request wallet auth | X-Wallet-Address, X-Timestamp, X-Wallet-Signature |
| x402 | Crypto payments | X-PAYMENT: ... |
- Navigate to Dashboard → API Keys
- Click "Create API Key"
- Name your key and set permissions
- Copy and securely store the key
<Tabs items={['cURL', 'JavaScript', 'Python']}> <Tabs.Tab>
curl -X GET "https://elizacloud.ai/api/v1/dashboard" \
-H "Authorization: Bearer ek_live_xxxxxxxxxxxx"</Tabs.Tab> <Tabs.Tab>
const response = await fetch('https://elizacloud.ai/api/v1/dashboard', {
headers: {
'Authorization': 'Bearer ek_live_xxxxxxxxxxxx',
},
});</Tabs.Tab> <Tabs.Tab>
import requests
response = requests.get(
'https://elizacloud.ai/api/v1/dashboard',
headers={'Authorization': 'Bearer ek_live_xxxxxxxxxxxx'}
)</Tabs.Tab>
| Prefix | Environment | Description |
|---|---|---|
ek_live_ |
Production | Live API access |
ek_test_ |
Testing | Sandbox environment |
Restrict keys to specific endpoints:
{
"name": "Production Chat Key",
"permissions": [
"chat:read",
"chat:write",
"embeddings:read"
],
"rateLimit": 100
}Permissions can be used to restrict what operations an API key can perform.
| Permission | Description |
|---|---|
chat |
Chat completions |
embeddings |
Generate embeddings |
images |
Image generation |
video |
Video generation |
voice |
Voice/TTS |
knowledge |
Knowledge base |
agents |
Agent management |
apps |
App management |
curl -X GET "https://elizacloud.ai/api/v1/api-keys" \
-H "Authorization: Bearer ek_live_xxxxxxxxxxxx"curl -X POST "https://elizacloud.ai/api/v1/api-keys/{id}/regenerate" \
-H "Authorization: Bearer ek_live_xxxxxxxxxxxx"curl -X DELETE "https://elizacloud.ai/api/v1/api-keys/{id}" \
-H "Authorization: Bearer ek_live_xxxxxxxxxxxx"For browser-based applications, use Privy authentication:
import { usePrivy } from "@privy-io/react-auth";
function MyComponent() {
const { login, authenticated, getAccessToken } = usePrivy();
const makeApiCall = async () => {
const token = await getAccessToken();
const response = await fetch("https://elizacloud.ai/api/v1/dashboard", {
credentials: "include",
headers: {
Authorization: `Bearer ${token}`,
},
});
};
}Wallet-based auth supports agents and headless clients that cannot use browser sessions.
- GET /api/auth/siwe/nonce — Returns
{ nonce, domain, uri, chainId, version, statement }. Nonce is one-time, 5 min TTL (Redis). Why nonce? Prevents replay; timestamp-only can be replayed within the window. - Build the EIP-4361 message with the nonce and sign it with the wallet.
- POST /api/auth/siwe/verify — Body
{ message, signature }. Server validates domain and signature, consumes the nonce, then finds or creates user/org and returnsapiKeywithuserandorganization. New wallets get initial free credits (configurable viaINITIAL_FREE_CREDITS). - Use the returned API key:
X-API-Key: <key>orAuthorization: Bearer <key>on subsequent requests.
Send on every request instead of storing an API key:
- X-Wallet-Address: Ethereum address (any case).
- X-Timestamp: Unix ms (must be within ±5 min of server time). Why? Binds the signature to a time window and limits replay.
- X-Wallet-Signature: Signature of the message
Eliza Cloud Authentication\nTimestamp: ${timestamp}\nMethod: ${method}\nPath: ${path}
so the signature is bound to this request. Why method + path? Prevents reusing the same signature on another endpoint.
If the wallet is unknown, the first valid signed request creates the account (same as SIWE signup). After that, any endpoint that uses requireAuthOrApiKey accepts wallet-header auth.
POST /api/v1/topup/10, /50, /100 (x402 payment-gated):
- With wallet sig headers: credits go to the signer’s wallet (no body
walletAddressneeded). - Without wallet sig: send body.walletAddress; that wallet’s org is credited. New wallets are created without initial free credits (payment only).
See Wallet API for full reference, WHYs, and file list.
Pay per request with cryptocurrency:
curl -X POST "https://elizacloud.ai/api/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "X-PAYMENT: <x402-payment-header>" \
-d '{"model": "gpt-4o", "messages": [...]}'- ✅ Use environment variables for API keys
- ✅ Rotate keys regularly
- ✅ Use minimal permissions
- ✅ Monitor key usage
- ✅ Use different keys for different environments
- ❌ Commit keys to version control
- ❌ Share keys between applications
- ❌ Use production keys in development
- ❌ Expose keys in client-side code
- ❌ Log API keys
# .env.local (never commit this file)
ELIZA_API_KEY=ek_live_xxxxxxxxxxxx// Access in your code
const apiKey = process.env.ELIZA_API_KEY;{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing authentication"
}
}Causes:
- Missing API key
- Invalid API key
- Expired session
{
"error": {
"code": "FORBIDDEN",
"message": "Insufficient permissions"
}
}Causes:
- Key lacks required permission
- Resource access denied
API keys have rate limits based on your plan:
| Plan | Rate Limit |
|---|---|
| Free | 60 req/min |
| Pro | 300 req/min |
| Enterprise | Custom |
Rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312860