# API Specification

## Overview

SOPHIAClaw exposes APIs at two levels:

1. **Gateway API**: WebSocket-based real-time API (port 37521)
2. **Channel APIs**: Platform-specific integrations (Telegram, Discord, etc.)

## Gateway API

### WebSocket Endpoint

**URL:** `ws://localhost:37521/v1/stream`

**Protocol:** Binary WebSocket with JSON message framing

### Connection

```javascript
const ws = new WebSocket("ws://localhost:37521/v1/stream");

ws.onopen = () => {
  // Send authentication
  ws.send(
    JSON.stringify({
      type: "auth",
      token: "your-auth-token",
    }),
  );
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  handleMessage(message);
};
```

### Message Types

#### Client → Gateway

```typescript
// Authentication
interface AuthMessage {
  type: "auth";
  token: string;
  client_type: "cli" | "web" | "mobile";
  capabilities: string[];
}

// Chat message
interface ChatMessage {
  type: "chat";
  session_id?: string; // Create new if omitted
  content: string;
  attachments?: Attachment[];
  context?: {
    files?: string[];
    tools?: string[];
  };
}

// Tool response (when agent requests tool execution)
interface ToolResponseMessage {
  type: "tool_response";
  tool_call_id: string;
  result: any;
  error?: string;
}

// Session management
interface SessionMessage {
  type: "session";
  action: "list" | "get" | "create" | "close" | "export";
  session_id?: string;
  params?: Record<string, any>;
}

// Configuration
interface ConfigMessage {
  type: "config";
  action: "get" | "set" | "reload";
  path?: string;
  value?: any;
}
```

#### Gateway → Client

```typescript
// Authentication response
interface AuthResponse {
  type: "auth_response";
  success: boolean;
  error?: string;
  session_id?: string;
  capabilities: string[];
}

// Streaming response chunk
interface StreamChunk {
  type: "stream";
  session_id: string;
  content: string;
  finish_reason?: "stop" | "length" | "tool_calls";
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
  };
}

// Tool execution request
interface ToolCallMessage {
  type: "tool_call";
  tool_call_id: string;
  tool: string;
  params: Record<string, any>;
  requires_approval?: boolean;
}

// Session event
interface SessionEvent {
  type: "session_event";
  session_id: string;
  event: "created" | "updated" | "closed" | "error";
  data?: Record<string, any>;
}

// System status
interface StatusMessage {
  type: "status";
  gateway: {
    version: string;
    uptime: number;
    connections: number;
  };
  channels: ChannelStatus[];
  memory: {
    sessions: number;
    tokens_used: number;
  };
}
```

### REST Endpoints

#### Health Check

```http
GET /health

Response 200:
{
  "status": "healthy",
  "version": "2.0.0",
  "uptime": 3600,
  "timestamp": "2025-02-24T13:30:00Z"
}
```

#### OpenAI-Compatible API

```http
POST /v1/chat/completions

Headers:
  Authorization: Bearer {token}
  Content-Type: application/json

Body:
{
  "model": "claude-sonnet-4",
  "messages": [
    {"role": "user", "content": "Hello"}
  ],
  "stream": true,
  "tools": [...]
}
```

#### Tool Invocation

```http
POST /v1/tools/invoke

Headers:
  Authorization: Bearer {token}

Body:
{
  "tool": "file_read",
  "params": {
    "path": "./README.md"
  },
  "session_id": "optional-session"
}

Response:
{
  "success": true,
  "result": "...file contents...",
  "execution_time": 0.123
}
```

#### Sessions Management

```http
# List sessions
GET /v1/sessions?agent_id=default&limit=10

# Get session
GET /v1/sessions/{session_id}

# Create session
POST /v1/sessions
{
  "agent_id": "default",
  "system_prompt": "optional",
  "metadata": {}
}

# Export session
GET /v1/sessions/{session_id}/export?format=markdown

# Delete session
DELETE /v1/sessions/{session_id}
```

## Telegram Bot API Integration

### Webhook Setup

```http
POST https://api.telegram.org/bot{token}/setWebhook

Body:
{
  "url": "https://your-gateway.com/telegram",
  "allowed_updates": ["message", "callback_query"]
}
```

### Incoming Message Format

```typescript
interface TelegramUpdate {
  update_id: number;
  message?: TelegramMessage;
  callback_query?: TelegramCallbackQuery;
}

interface TelegramMessage {
  message_id: number;
  from: TelegramUser;
  chat: TelegramChat;
  date: number;
  text?: string;
  document?: TelegramDocument;
  photo?: TelegramPhotoSize[];
}
```

### Gateway → Telegram

```typescript
// Send message
interface SendMessageRequest {
  chat_id: number | string;
  text: string;
  parse_mode?: "Markdown" | "HTML";
  reply_markup?: InlineKeyboardMarkup;
}

// Send file
interface SendDocumentRequest {
  chat_id: number | string;
  document: string; // file_id or URL
  caption?: string;
}
```

## Discord Bot API

### Gateway Intents

```typescript
const intents = [
  GatewayIntentBits.Guilds,
  GatewayIntentBits.GuildMessages,
  GatewayIntentBits.MessageContent,
  GatewayIntentBits.DirectMessages,
];
```

### Event Handlers

```typescript
// Message received
client.on("messageCreate", async (message) => {
  if (message.author.bot) return;

  const session = await getOrCreateSession({
    channel: "discord",
    user_id: message.author.id,
    guild_id: message.guild?.id,
  });

  const response = await agent.processMessage({
    session,
    content: message.content,
  });

  await message.reply(response);
});
```

### Message Format

```typescript
interface DiscordMessage {
  id: string;
  content: string;
  author: {
    id: string;
    username: string;
    bot: boolean;
  };
  guild_id?: string;
  channel_id: string;
  attachments: Attachment[];
}
```

## Slack Integration

### Socket Mode

```typescript
const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN,
});

app.message(async ({ message, say }) => {
  const response = await agent.processMessage({
    channel: "slack",
    user_id: message.user,
    content: message.text,
  });

  await say(response);
});
```

### Block Kit Integration

```typescript
interface SlackBlock {
  type: "section" | "divider" | "actions";
  text?: {
    type: "mrkdwn" | "plain_text";
    text: string;
  };
  elements?: ButtonElement[];
}

// Tool approval flow
const approvalBlocks = [
  {
    type: "section",
    text: {
      type: "mrkdwn",
      text: "Tool execution requested: `file_write`",
    },
  },
  {
    type: "actions",
    elements: [
      {
        type: "button",
        text: "Approve",
        action_id: "approve_tool",
        style: "primary",
      },
      {
        type: "button",
        text: "Deny",
        action_id: "deny_tool",
        style: "danger",
      },
    ],
  },
];
```

## WhatsApp Integration

### Web-based Integration

Uses `whatsapp-web.js` with Puppeteer:

```typescript
const client = new Client({
  authStrategy: new LocalAuth({
    dataPath: "./.sophiaclaw/whatsapp-session",
  }),
  puppeteer: {
    headless: true,
    args: ["--no-sandbox"],
  },
});

client.on("message", async (msg) => {
  if (msg.fromMe) return;

  const response = await agent.processMessage({
    channel: "whatsapp",
    user_id: msg.from,
    content: msg.body,
  });

  await msg.reply(response);
});

// QR Code for initial authentication
client.on("qr", (qr) => {
  console.log("Scan QR:", qr);
});
```

## Authentication

### Token Types

| Token Type   | Purpose               | Storage                                    |
| ------------ | --------------------- | ------------------------------------------ |
| Gateway Auth | WebSocket/API access  | `~/.sophiaclaw/credentials/gateway.enc`    |
| Telegram     | Bot API access        | `~/.sophiaclaw/credentials/telegram.enc`   |
| Discord      | Bot API access        | `~/.sophiaclaw/credentials/discord.enc`    |
| LLM API      | SOPHIAClaw/OpenRouter | `~/.sophiaclaw/credentials/sophiaclaw.enc` |

### Authentication Flow

```
1. Client connects to WebSocket
2. Server sends auth challenge
3. Client responds with signed token
4. Server validates token
5. Connection established with capabilities
```

## Error Handling

### Error Codes

| Code | Meaning               | HTTP Status |
| ---- | --------------------- | ----------- |
| 4000 | Invalid request       | 400         |
| 4001 | Authentication failed | 401         |
| 4002 | Session not found     | 404         |
| 4003 | Rate limited          | 429         |
| 4004 | Tool execution failed | 500         |
| 4005 | LLM provider error    | 502         |

### Error Response Format

```typescript
interface ErrorResponse {
  error: {
    code: number;
    message: string;
    details?: Record<string, any>;
    retry_after?: number;
  };
}
```

## Rate Limiting

### Gateway Limits

| Endpoint             | Limit | Window   |
| -------------------- | ----- | -------- |
| /v1/chat/completions | 60    | 1 minute |
| /v1/tools/invoke     | 120   | 1 minute |
| /v1/sessions/\*      | 30    | 1 minute |
| WebSocket messages   | 100   | 1 minute |

### Rate Limit Headers

```http
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1708785600
X-RateLimit-Retry-After: 60
```

## Webhooks

### Incoming Webhooks

```http
POST /webhooks/telegram
POST /webhooks/discord
POST /webhooks/slack
```

All incoming webhooks:

- Validate signatures (HMAC)
- Rate limited per source
- Async processing with queue

### Outgoing Webhooks

Configure callbacks for events:

```yaml
webhooks:
  outgoing:
    - url: https://your-server.com/claw-events
      events: ["session.created", "tool.executed"]
      secret: your-webhook-secret
```

## Versioning

API versions are URL-prefixed:

- `/v1/` - Current stable
- `/v2/` - Beta (when available)

Breaking changes only in major versions.
