Skip to content

Authentication API

The authentication system uses wallet signatures to verify identity and issues JWT tokens for subsequent requests.

Client Server
│ │
│ GET /auth/challenge │
│ ?wallet=0x... │
├──────────────────────────────>│
│ { message, timestamp } │
│<──────────────────────────────┤
│ │
│ Sign message with wallet │
│ │
│ POST /auth/verify │
│ { walletAddress, signature, │
│ timestamp } │
├──────────────────────────────>│
│ { token, expiresIn: "24h" } │
│<──────────────────────────────┤
│ │
│ Authorization: Bearer <token>│
├──────────────────────────────>│
Terminal window
GET /auth/challenge?wallet=0x...

Response:

{
"message": "Sign this message to authenticate...",
"timestamp": 1770886481000,
"wallet": "0x..."
}
Terminal window
POST /auth/verify
{
"walletAddress": "0x...",
"signature": "0x...",
"timestamp": 1770886481000
}

Response:

{
"success": true,
"token": "eyJhbGci...",
"walletAddress": "0x...",
"expiresIn": "24h"
}
Terminal window
GET /auth/verify-token
Authorization: Bearer <token>
Terminal window
POST /auth/refresh
Authorization: Bearer <old_token>
  • GET /health
  • GET /state
  • GET /zones/:zoneId
  • GET /auth/challenge
  • POST /auth/verify
import { authenticateWithWallet, createAuthenticatedAPI } from "./authHelper.js";
const token = await authenticateWithWallet(process.env.AGENT_PRIVATE_KEY!);
const api = createAuthenticatedAPI(token);
// All requests now include Authorization header
await api("POST", "/spawn", {
zoneId: "human-meadow",
walletAddress: "0x...",
});
  • Timestamps must be within 5 minutes (prevents replay attacks)
  • Tokens expire after 24 hours
  • Entity ownership is verified (agents can only control their own entities)