REST API Reference#

The ChatAPI REST API provides HTTP endpoints for chat operations. All endpoints require authentication and return JSON responses.

Authentication#

Include these headers with every request:

X-API-Key: your-tenant-api-key
X-User-Id: user-identifier

Rooms#

Create Room#

Create a new chat room (DM, group, or channel).

POST /rooms

Request Body:

{
  "type": "dm" | "group" | "channel",
  "members": ["user1", "user2"],
  "name": "Optional room name"
}

Response:

{
  "room_id": "room_abc123",
  "type": "dm",
  "unique_key": "dm:user1:user2",
  "name": null,
  "last_seq": 0,
  "created_at": "2025-12-13T12:00:00Z"
}

Status Codes:

  • 201 - Room created successfully
  • 400 - Invalid request parameters
  • 401 - Authentication failed
  • 409 - Room already exists (for DMs)

Get Room#

Retrieve room information.

GET /rooms/{room_id}

Response:

{
  "room_id": "room_abc123",
  "type": "group",
  "name": "Team Chat",
  "last_seq": 42,
  "created_at": "2025-12-13T12:00:00Z"
}

List Room Members#

Get all members of a room.

GET /rooms/{room_id}/members

Response:

[
  {
    "user_id": "user1",
    "role": "admin",
    "joined_at": "2025-12-13T12:00:00Z"
  },
  {
    "user_id": "user2",
    "role": "member",
    "joined_at": "2025-12-13T12:05:00Z"
  }
]

Messages#

Send Message#

Send a message to a room.

POST /rooms/{room_id}/messages

Request Body:

{
  "content": "Hello, world!",
  "meta": {
    "type": "text",
    "mentions": ["user2"]
  }
}

Response:

{
  "message_id": "msg_abc123",
  "seq": 43,
  "created_at": "2025-12-13T12:10:00Z"
}

Get Messages#

Retrieve messages from a room.

GET /rooms/{room_id}/messages?after_seq=40&limit=50

Query Parameters:

  • after_seq (optional): Get messages after this sequence number
  • limit (optional): Maximum messages to return (default: 50, max: 100)

Response:

[
  {
    "message_id": "msg_abc123",
    "sender_id": "user1",
    "seq": 41,
    "content": "Hello, world!",
    "meta": {
      "type": "text",
      "mentions": ["user2"]
    },
    "created_at": "2025-12-13T12:10:00Z"
  }
]

Delivery & Acknowledgments#

Acknowledge Messages#

Mark messages as delivered up to a specific sequence number.

POST /acks

Request Body:

{
  "room_id": "room_abc123",
  "seq": 43
}

Response:

{
  "success": true
}

Notifications#

Send Notification#

Send a notification to users or room members.

POST /notify

Request Body:

{
  "topic": "order.shipped",
  "payload": {
    "order_id": "12345",
    "tracking_number": "1Z999AA1234567890"
  },
  "targets": {
    "user_ids": ["user1", "user2"],
    "room_id": "room_abc123",
    "topic_subscribers": true
  }
}

Response:

{
  "notification_id": "notif_abc123",
  "created_at": "2025-12-13T12:15:00Z"
}

Health & Monitoring#

Health Check#

Check service health and status.

GET /health

Response:

{
  "status": "ok",
  "uptime": "2h30m45s",
  "db_writable": true
}

Dead Letters (Admin)#

View failed deliveries (admin endpoint).

GET /admin/dead-letters?tenant_id=tenant_abc&limit=100

Query Parameters:

  • tenant_id (required): Tenant identifier
  • limit (optional): Maximum results (default: 50, max: 1000)

Response:

{
  "failed_messages": [
    {
      "message_id": "msg_abc123",
      "user_id": "user1",
      "room_id": "room_abc123",
      "attempts": 5,
      "last_attempt_at": "2025-12-13T12:20:00Z",
      "error": "connection timeout"
    }
  ],
  "failed_notifications": [
    {
      "notification_id": "notif_abc123",
      "topic": "order.shipped",
      "attempts": 3,
      "last_attempt_at": "2025-12-13T12:25:00Z",
      "error": "user offline"
    }
  ]
}

Error Responses#

All endpoints may return these error formats:

Validation Error:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid room type. Must be one of: dm, group, channel",
    "field": "type"
  }
}

Authentication Error:

{
  "success": false,
  "error": {
    "code": "AUTHENTICATION_ERROR",
    "message": "Invalid API key"
  }
}

Rate Limit Exceeded:

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 60 seconds"
  }
}

Rate Limiting#

ChatAPI implements per-tenant rate limiting:

  • Default Limit: 100 requests per second per tenant
  • Response Headers:
    X-RateLimit-Limit: 100
    X-RateLimit-Remaining: 95
    X-RateLimit-Reset: 1640995200
  • 429 Status: Returned when limits are exceeded
  • Retry-After Header: Indicates when to retry

Content Types#

  • Request Body: application/json
  • Response Body: application/json
  • Character Encoding: UTF-8

Time Formats#

All timestamps use ISO 8601 format:

2025-12-13T12:00:00Z
2025-12-13T12:00:00.123456Z

Pagination#

Endpoints that return lists support pagination:

  • limit: Maximum items per page (default: 50, max: 100)
  • offset: Number of items to skip (default: 0)

Versioning#

API versioning is handled via URL paths:

  • Current version: No prefix (v1 implied)
  • Future versions: /v2/, /v3/, etc.

SDK Examples#

JavaScript (Fetch API)#

const API_KEY = 'your-api-key';
const USER_ID = 'user123';

async function sendMessage(roomId, content) {
  const response = await fetch(`/rooms/${roomId}/messages`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
      'X-User-Id': USER_ID
    },
    body: JSON.stringify({ content })
  });

  return response.json();
}

Python (requests)#

import requests

API_KEY = 'your-api-key'
USER_ID = 'user123'
BASE_URL = 'https://your-chatapi.com'

def send_message(room_id, content):
    headers = {
        'Content-Type': 'application/json',
        'X-API-Key': API_KEY,
        'X-User-Id': USER_ID
    }

    data = {'content': content}

    response = requests.post(
        f'{BASE_URL}/rooms/{room_id}/messages',
        json=data,
        headers=headers
    )

    return response.json()

Go (net/http)#

package main

import (
    "bytes"
    "encoding/json"
    "net/http"
)

const (
    apiKey  = "your-api-key"
    userID  = "user123"
    baseURL = "https://your-chatapi.com"
)

func sendMessage(roomID, content string) error {
    data := map[string]string{"content": content}
    jsonData, _ := json.Marshal(data)

    req, _ := http.NewRequest("POST",
        baseURL+"/rooms/"+roomID+"/messages",
        bytes.NewBuffer(jsonData))

    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-API-Key", apiKey)
    req.Header.Set("X-User-Id", userID)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    return nil
}