API Documentation
The S8t API lets you manage users, agents, email, and storage programmatically.
Base URL: https://api.s8t.ai
Authentication
User endpoints require a JWT obtained via magic link.
Pass as Authorization: Bearer <jwt>.
Agent endpoints (email send, storage) use agent bearer tokens
(s8t_ag_...).
Ingest endpoint uses
X-Ingest-Secret header (internal only).
Endpoints
Authentication
/auth/magic-link Send a magic link to the user's email for passwordless authentication.
POST /auth/magic-link
Content-Type: application/json
{
"email": "arun@example.com"
} {
"ok": true,
"message": "Magic link sent"
} /auth/verify Verify a magic link token. Sets a session cookie (web) or redirects to the app with a JWT.
GET /auth/verify?token={uuid} 302 Redirect
Set-Cookie: s8t_session={jwt}; HttpOnly; Secure
// Or if ?app=true:
302 Redirect → openclaw://auth?token={jwt} /auth/refresh Refresh an expiring JWT. Tokens expire after 7 days.
POST /auth/refresh
Authorization: Bearer {jwt} {
"token": "eyJhbG..."
} Users
/users Create a new user and claim a username namespace. Usernames: 3-40 chars, lowercase alphanumeric with hyphens.
POST /users
Content-Type: application/json
Authorization: Bearer {jwt}
{
"username": "arun",
"email": "arun@example.com"
} {
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "arun",
"email_domain": "arun.s8t.ai"
} /users/:username/available Check if a username is available for registration.
GET /users/arun/available
{
"username": "arun",
"available": true
} Agents
/users/:user_id/agents Create a new agent with email address and Drive folder. Returns a bearer token for API access.
POST /users/550e8400-.../agents
Content-Type: application/json
Authorization: Bearer {jwt}
{
"name": "claude"
} {
"id": "660e8400-e29b-41d4-a716-446655440000",
"name": "claude",
"email": "claude@arun.s8t.ai",
"agent_token": "s8t_ag_a1b2c3d4e5f6...",
"drive_folder": "/S8t/claude/"
} Storage Connection
/auth/google/connect
Initiate Google OAuth to connect Drive. Requests drive.file scope (only app-created files).
302 Redirect → https://accounts.google.com/o/oauth2/v2/auth?...
/auth/google/callback OAuth callback. Exchanges code for tokens, creates /S8t/ folder structure, stores encrypted refresh token.
302 Redirect → /dashboard (success) 302 Redirect → /dashboard?error=drive_failed (failure)
/email/ingest Ingest inbound email from Cloudflare Email Worker.
Internal — requires X-Ingest-Secret header
POST /email/ingest
Content-Type: message/rfc822
X-Envelope-To: claude@arun.s8t.ai
X-Envelope-From: sender@example.com
X-Ingest-Secret: {secret}
{raw RFC822 email bytes} 200 OK — Queued for processing 401 Unauthorized — Bad or missing secret 404 Not Found — Unknown agent or user
/email/send Send email from an agent's address via Amazon SES.
Requires agent bearer token
POST /email/send
Content-Type: application/json
Authorization: Bearer s8t_ag_a1b2c3d4...
{
"to": "human@example.com",
"subject": "Hello from Claude",
"body": "Plain text body",
"html": "<p>HTML body</p>"
} {
"message_id": "<uuid@arun.s8t.ai>"
} Storage
All storage endpoints require an agent bearer token. Paths are relative to the agent's Drive folder.
/storage/files/:path Read a file from the agent's Drive folder.
GET /storage/files/notes/todo.md Authorization: Bearer s8t_ag_a1b2c3d4...
Content-Type: text/markdown
{file contents} /storage/files/:path Write a file to the agent's Drive folder. Creates parent directories if needed.
PUT /storage/files/notes/todo.md
Content-Type: text/markdown
Authorization: Bearer s8t_ag_a1b2c3d4...
{file contents} {
"ok": true,
"drive_file_id": "1a2b3c4d..."
} /storage/files/:path?list List files and folders in a directory.
GET /storage/files/notes/?list Authorization: Bearer s8t_ag_a1b2c3d4...
{
"files": [
{
"name": "todo.md",
"size": 1234,
"modified": "2026-02-11T10:30:00Z",
"type": "file"
},
{
"name": "drafts",
"type": "folder"
}
]
} /storage/files/:path Delete a file from the agent's Drive folder.
DELETE /storage/files/notes/todo.md Authorization: Bearer s8t_ag_a1b2c3d4...
{
"ok": true
} Error Responses
{
"error": "not_found",
"message": "Agent not found"
} 400 Bad request — invalid parameters 401 Unauthorized — missing or invalid token 403 Forbidden — insufficient permissions 404 Not found — resource doesn't exist 409 Conflict — username already taken 429 Rate limited — too many requests