v0.9.1 routes - nself-org/nchat GitHub Wiki

API Routes Documentation - v0.9.1

Quick reference for all API routes added/completed in v0.9.1.

Channels & Communities

Category Management

List Categories

GET /api/channels/categories?workspaceId={uuid}&includeChannels=true

Response:

{
  "success": true,
  "categories": [...],
  "pagination": {
    "total": 10,
    "offset": 0,
    "limit": 50,
    "hasMore": false
  }
}

Create Category

POST /api/channels/categories
Authorization: Bearer {token}
Content-Type: application/json

{
  "name": "Important Channels",
  "description": "High priority channels",
  "workspaceId": "uuid",
  "position": 0,
  "isCollapsed": false
}

Permissions: admin, owner


Channel Category Assignment

Assign Channel to Category

PUT /api/channels/{channelId}/category
Authorization: Bearer {token}
Content-Type: application/json

{
  "categoryId": "uuid",
  "position": 2,
  "reorderExisting": true
}

Response:

{
  "success": true,
  "channel": {
    "id": "uuid",
    "name": "general",
    "category_id": "uuid",
    "position": 2,
    "updated_at": "2026-02-03T..."
  },
  "message": "Channel assigned to category successfully"
}

Permissions: admin, owner, moderator

Remove Channel from Category

DELETE /api/channels/{channelId}/category
Authorization: Bearer {token}

Permissions: admin, owner, moderator


Guilds (Discord-style Servers)

List Guilds

GET /api/channels/guild?organizationId={uuid}&isDiscoverable=true&limit=20

Create Guild

POST /api/channels/guild
Authorization: Bearer {token}
Content-Type: application/json

{
  "name": "My Community",
  "slug": "my-community",
  "description": "A place for friends",
  "iconUrl": "https://...",
  "bannerUrl": "https://...",
  "vanityUrl": "mycommunity",
  "isDiscoverable": true,
  "verificationLevel": 1,
  "explicitContentFilter": 1,
  "maxMembers": 5000,
  "maxChannels": 100,
  "maxFileSizeMb": 25
}

Note: Auto-creates default categories and channels.


Broadcast Lists (WhatsApp-style)

List Broadcast Lists

GET /api/channels/broadcast?workspaceId={uuid}&ownerId={uuid}

Create Broadcast List

POST /api/channels/broadcast
Authorization: Bearer {token}
Content-Type: application/json

{
  "workspaceId": "uuid",
  "name": "Product Updates",
  "description": "Weekly product announcements",
  "subscriptionMode": "invite",
  "allowReplies": false,
  "showSenderName": true,
  "trackDelivery": true,
  "trackReads": false,
  "maxSubscribers": 1000,
  "initialSubscriberIds": ["uuid1", "uuid2"]
}

WebRTC & Calls

Call Recording

Start Recording

POST /api/calls/{callId}/recording
Authorization: Bearer {token}
Content-Type: application/json

{
  "format": "mp4",
  "quality": "high",
  "includeAudio": true,
  "includeVideo": true,
  "includeScreenShare": true,
  "layout": "grid"
}

Options:

  • Format: mp4, webm, mp3
  • Quality: low, medium, high, hd
  • Layout: grid, spotlight, presentation

Get Recording Status

GET /api/calls/{callId}/recording
Authorization: Bearer {token}

Stop Recording

DELETE /api/calls/{callId}/recording
Authorization: Bearer {token}

Call Participants

List Participants

GET /api/calls/{callId}/participants
Authorization: Bearer {token}

Add Participant (Invite)

POST /api/calls/{callId}/participants
Authorization: Bearer {token}
Content-Type: application/json

{
  "userIds": ["uuid1", "uuid2"]
}

Remove Participant (Kick)

DELETE /api/calls/{callId}/participants/{userId}
Authorization: Bearer {token}

Live Streaming

Stream Analytics

Get Analytics

GET /api/streams/{streamId}/analytics
Authorization: Bearer {token}

Response:

{
  "success": true,
  "analytics": {
    "viewerCount": 42,
    "peakViewers": 68,
    "duration": 3600,
    "chatMessages": 234,
    "reactions": {
      "likes": 156,
      "loves": 89,
      "fire": 45
    }
  }
}

Stream Viewers

List Viewers

GET /api/streams/{streamId}/viewers?includeMetadata=true&includeInactive=false&sortBy=joinTime&sortOrder=asc&limit=100&offset=0

Query Parameters:

  • includeMetadata (boolean): Include LiveKit participant data
  • includeInactive (boolean): Include viewers who left
  • sortBy (enum): joinTime, username, duration
  • sortOrder (enum): asc, desc
  • limit (int): 1-1000, default 100
  • offset (int): >= 0, default 0

Response:

{
  "success": true,
  "viewers": [
    {
      "id": "uuid",
      "userId": "uuid",
      "username": "john_doe",
      "displayName": "John Doe",
      "avatarUrl": "https://...",
      "joinedAt": "2026-02-03T12:00:00Z",
      "duration": 1234,
      "isActive": true,
      "isAudioEnabled": true,
      "isVideoEnabled": false,
      "isScreenSharing": false,
      "connectionQuality": "excellent",
      "livekitParticipant": { ... }
    }
  ],
  "stats": {
    "active": 15,
    "total": 42,
    "streamStatus": "connected",
    "duration": 3600
  },
  "pagination": {
    "total": 42,
    "offset": 0,
    "limit": 100,
    "hasMore": false
  },
  "stream": {
    "id": "uuid",
    "name": "Stream by John",
    "type": "video",
    "status": "connected",
    "startedAt": "2026-02-03T12:00:00Z",
    "initiator": {
      "id": "uuid",
      "username": "john_doe",
      "displayName": "John Doe",
      "avatarUrl": "https://..."
    }
  }
}

Authentication

ID.me OAuth

OAuth Callback

GET /api/auth/idme/callback?code={code}&state={state}

Response: Redirects to app with session cookie


Email Verification

Resend Verification Email

POST /api/auth/resend-verification
Content-Type: application/json

{
  "email": "[email protected]"
}

Rate Limit: 3 requests per hour per IP

Response:

{
  "success": true,
  "message": "If your account exists and is unverified, a verification email has been sent."
}

Note: Always returns success to prevent email enumeration.

Verify Email

GET /api/auth/verify-email/{token}

Response: Redirects to app with verified status


Error Responses

All routes follow this error format:

{
  "success": false,
  "error": "Error message",
  "details": {
    "field": ["validation error"]
  }
}

HTTP Status Codes

  • 200 OK - Success (GET, PUT, DELETE)
  • 201 Created - Success (POST)
  • 400 Bad Request - Validation error
  • 401 Unauthorized - Authentication required
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Resource not found
  • 409 Conflict - Duplicate resource
  • 500 Internal Server Error - Server error

Authentication

Most routes require authentication via Bearer token:

Authorization: Bearer {token}

Or user ID header (dev mode):

x-user-id: {userId}
x-user-role: {role}

Rate Limiting

Rate limits apply to:

  • Email verification: 3 per hour per IP
  • Authentication endpoints: varies by endpoint

Rate limit headers:

X-RateLimit-Limit: 3
X-RateLimit-Remaining: 2
X-RateLimit-Reset: 1675436400

Pagination

List endpoints support pagination:

Query Parameters:

  • limit: Items per page (default varies by endpoint)
  • offset: Skip N items

Response:

{
  "pagination": {
    "total": 100,
    "offset": 0,
    "limit": 20,
    "hasMore": true
  }
}

WebSocket Events

Real-time updates via Socket.io:

Channel Events

  • channel:updated
  • channel:category_changed
  • category:created
  • category:updated
  • category:deleted

Call Events

  • call:participant_joined
  • call:participant_left
  • call:recording_started
  • call:recording_stopped

Stream Events

  • stream:viewer_joined
  • stream:viewer_left
  • stream:stats_updated

GraphQL Subscriptions

Alternative to WebSocket events, use GraphQL subscriptions:

subscription SubscribeToCategoryUpdates($workspaceId: uuid!) {
  nchat_channel_categories(
    where: { workspace_id: { _eq: $workspaceId } }
    order_by: { position: asc }
  ) {
    id
    name
    position
    channels {
      id
      name
      position
    }
  }
}

Testing Endpoints

Use curl for testing:

# Test category assignment
curl -X PUT http://localhost:3000/api/channels/{channelId}/category \
  -H "Content-Type: application/json" \
  -H "x-user-id: {userId}" \
  -H "x-user-role: admin" \
  -d '{"categoryId": "{categoryId}", "position": 1}'

# Test stream viewers
curl http://localhost:3000/api/streams/{streamId}/viewers?limit=10&sortBy=joinTime

# Test resend verification
curl -X POST http://localhost:3000/api/auth/resend-verification \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'

See Also


Version: v0.9.1 Last Updated: February 3, 2026

⚠️ **GitHub.com Fallback** ⚠️