Skip to main content

API Reference

This comprehensive API reference covers all available endpoints in the Chirp REST API for developers and integrators.

API Overview

Base URL

Production: https://your-domain.com/api
Development: http://localhost:3001/api

Authentication

Chirp uses JWT (JSON Web Token) authentication. Include the token in your requests:

Authorization: Bearer <your-jwt-token>

Rate Limiting

  • General API Endpoints: 2000 requests per minute
  • Authentication Endpoints: 25 requests per 15 minutes
  • Admin Endpoints: 10 requests per 15 minutes
  • Auth Status Checks: 500 requests per minute
  • Password Reset: 3 requests per hour
  • Email Verification: 3 requests per 15 minutes

Response Format

All API responses follow this structure:

{
"success": true,
"data": {},
"message": "Operation successful",
"timestamp": "2024-01-01T00:00:00.000Z"
}

Error responses:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": []
},
"timestamp": "2024-01-01T00:00:00.000Z"
}

Authentication

Register User

POST /auth/register

Request Body:

{
"username": "string (3-32 chars)",
"email": "string (valid email)",
"password": "string (8-128 chars)",
"inviteCode": "string (optional)"
}

Response:

{
"success": true,
"data": {
"user": {
"id": "uuid",
"username": "newuser",
"email": "user@example.com",
"avatar": null,
"createdAt": "2024-01-01T00:00:00.000Z"
},
"token": "jwt_token_here"
}
}

Login

POST /auth/login

Request Body:

{
"email": "string",
"password": "string"
}

Response:

{
"success": true,
"data": {
"user": {
"id": "uuid",
"username": "existinguser",
"email": "user@example.com",
"avatar": "avatar_url"
},
"token": "jwt_token_here"
}
}

Refresh Token

POST /auth/refresh

Headers:

Authorization: Bearer <refresh-token>

Response:

{
"success": true,
"data": {
"token": "new_jwt_token_here"
}
}

Logout

POST /auth/logout

Headers:

Authorization: Bearer <jwt-token>

Users

Get Current User

GET /users/me

Response:

{
"success": true,
"data": {
"id": "uuid",
"username": "username",
"email": "user@example.com",
"avatar": "avatar_url",
"banner": "banner_url",
"bio": "User biography",
"status": "online|idle|dnd|invisible",
"flags": 0,
"createdAt": "2024-01-01T00:00:00.000Z"
}
}

Update User Profile

PATCH /users/me

Request Body:

{
"username": "string (optional)",
"avatar": "file (optional)",
"banner": "file (optional)",
"bio": "string (optional, max 500 chars)",
"status": "string (optional)"
}

Get User by ID

GET /users/:userId

Response:

{
"success": true,
"data": {
"id": "uuid",
"username": "username",
"avatar": "avatar_url",
"banner": "banner_url",
"bio": "User biography",
"status": "online",
"flags": 0,
"mutualServers": ["server_id"],
"createdAt": "2024-01-01T00:00:00.000Z"
}
}

Search Users

GET /users/search?q=query&limit=10&offset=0

Query Parameters:

  • q: Search query (username)
  • limit: Number of results (max 50)
  • offset: Pagination offset

Response:

{
"success": true,
"data": {
"users": [
{
"id": "uuid",
"username": "matchinguser",
"avatar": "avatar_url",
"status": "online"
}
],
"total": 1,
"hasMore": false
}
}

Servers

Get User Servers

GET /servers

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"name": "Server Name",
"icon": "icon_url",
"ownerId": "uuid",
"memberCount": 150,
"isOwner": false,
"permissions": 104324673,
"joinedAt": "2024-01-01T00:00:00.000Z"
}
]
}

Create Server

POST /servers

Request Body:

{
"name": "string (2-100 chars)",
"icon": "file (optional)",
"region": "string (optional)"
}

Response:

{
"success": true,
"data": {
"id": "uuid",
"name": "New Server",
"icon": null,
"ownerId": "user_uuid",
"createdAt": "2024-01-01T00:00:00.000Z"
}
}

Get Server Details

GET /servers/:serverId

Response:

{
"success": true,
"data": {
"id": "uuid",
"name": "Server Name",
"icon": "icon_url",
"banner": "banner_url",
"description": "Server description",
"ownerId": "uuid",
"memberCount": 150,
"channelCount": 12,
"emojiCount": 5,
"boostLevel": 0,
"features": ["COMMUNITY", "NEWS"],
"permissions": 104324673,
"joinedAt": "2024-01-01T00:00:00.000Z"
}
}

Update Server

PATCH /servers/:serverId

Requires Permission: MANAGE_SERVER

Request Body:

{
"name": "string (optional)",
"icon": "file (optional)",
"banner": "file (optional)",
"description": "string (optional)",
"features": ["string array (optional)"]
}

Delete Server

DELETE /servers/:serverId

Requires Permission: SERVER_OWNER

Channels

Get Server Channels

GET /servers/:serverId/channels

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"name": "general",
"type": 0, // 0: text, 2: voice, 4: category, 15: forum
"topic": "General discussion",
"parentId": "category_uuid",
"position": 0,
"permissionOverwrites": [],
"nsfw": false,
"lastMessageId": "message_uuid",
"createdAt": "2024-01-01T00:00:00.000Z"
}
]
}

Create Channel

POST /servers/:serverId/channels

Requires Permission: MANAGE_CHANNELS

Request Body:

{
"name": "string (1-100 chars)",
"type": 0, // Channel type
"topic": "string (optional, max 1024 chars)",
"parentId": "uuid (optional)",
"permissionOverwrites": [
{
"id": "role_or_user_id",
"type": 0, // 0: role, 1: member
"allow": "string (permission bits)",
"deny": "string (permission bits)"
}
]
}

Get Channel Messages

GET /channels/:channelId/messages?limit=50&before=message_uuid&after=message_uuid

Requires Permission: READ_MESSAGES

Query Parameters:

  • limit: Number of messages (1-100)
  • before: Get messages before this message ID
  • after: Get messages after this message ID

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"channelId": "uuid",
"author": {
"id": "uuid",
"username": "username",
"avatar": "avatar_url",
"bot": false
},
"content": "Message content",
"timestamp": "2024-01-01T00:00:00.000Z",
"editedTimestamp": null,
"mentions": [],
"mentionRoles": [],
"attachments": [],
"embeds": [],
"reactions": [],
"pinned": false,
"type": 0
}
]
}

Send Message

POST /channels/:channelId/messages

Requires Permission: SEND_MESSAGES

Request Body (JSON):

{
"content": "string (max 2000 chars)",
"embeds": [
{
"title": "string",
"description": "string",
"url": "string",
"color": "number (hex color)",
"fields": [
{
"name": "string",
"value": "string",
"inline": "boolean"
}
]
}
],
"tts": "boolean"
}

Request Body (multipart/form-data):

content: string
file1: file (optional)
file2: file (optional)
... up to 10 files

Response:

{
"success": true,
"data": {
"id": "uuid",
"channelId": "uuid",
"author": {
"id": "uuid",
"username": "username",
"avatar": "avatar_url"
},
"content": "Message content",
"timestamp": "2024-01-01T00:00:00.000Z",
"attachments": [
{
"id": "uuid",
"filename": "image.png",
"size": 12345,
"url": "attachment_url",
"proxyUrl": "proxy_url",
"width": 1920,
"height": 1080,
"contentType": "image/png"
}
]
}
}

Edit Message

PATCH /channels/:channelId/messages/:messageId

Requires: User must be message author or have MANAGE_MESSAGES

Request Body:

{
"content": "string (max 2000 chars)"
}

Delete Message

DELETE /channels/:channelId/messages/:messageId

Requires: User must be message author or have MANAGE_MESSAGES

Reactions

Add Reaction

PUT /channels/:channelId/messages/:messageId/reactions/:emoji

Requires Permission: READ_MESSAGE_HISTORY

URL Parameters:

  • emoji: URL-encoded emoji (e.g., 👍 -> %F0%9F%91%8D)

Remove Reaction

DELETE /channels/:channelId/messages/:messageId/reactions/:emoji

Requires: User must have added the reaction or have MANAGE_MESSAGES

Get Reactions

GET /channels/:channelId/messages/:messageId/reactions/:emoji

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"username": "username",
"avatar": "avatar_url",
"bot": false
}
]
}

Threads

Create Thread

POST /channels/:channelId/messages/:messageId/threads

Requires Permission: CREATE_PUBLIC_THREADS

Request Body:

{
"name": "string (1-100 chars)",
"autoArchiveDuration": 1440 // 60, 1440, 4320, 10080 minutes
}

Get Thread Members

GET /channels/:threadId/thread-members

Response:

{
"success": true,
"data": [
{
"userId": "uuid",
"joinTimestamp": "2024-01-01T00:00:00.000Z",
"flags": 0
}
]
}

Join Thread

PUT /channels/:threadId/thread-members/@me

Leave Thread

DELETE /channels/:threadId/thread-members/@me

Media and Files

Upload File

POST /media/upload

Request Body (multipart/form-data):

file: file (required)
channelId: uuid (optional)

Response:

{
"success": true,
"data": {
"id": "uuid",
"filename": "document.pdf",
"originalName": "my-document.pdf",
"size": 1048576,
"mimeType": "application/pdf",
"url": "https://cdn.example.com/media/uuid/document.pdf",
"thumbnailUrl": "https://cdn.example.com/thumbnails/uuid.jpg",
"uploadedBy": "user_uuid",
"createdAt": "2024-01-01T00:00:00.000Z"
}
}

Get Media Info

GET /media/:mediaId

Response:

{
"success": true,
"data": {
"id": "uuid",
"filename": "image.png",
"originalName": "screenshot.png",
"size": 2048576,
"mimeType": "image/png",
"url": "https://cdn.example.com/media/uuid/image.png",
"thumbnailUrl": "https://cdn.example.com/thumbnails/uuid.jpg",
"width": 1920,
"height": 1080,
"uploadedBy": "user_uuid",
"uploadedAt": "2024-01-01T00:00:00.000Z"
}
}

Delete Media

DELETE /media/:mediaId

Requires: User must have uploaded the file or have MANAGE_MESSAGES

Direct Messages

Get DM Channels

GET /users/me/channels

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"type": 1, // 1: DM, 3: Group DM
"recipients": [
{
"id": "uuid",
"username": "friend",
"avatar": "avatar_url"
}
],
"lastMessageId": "uuid",
"lastMessageTimestamp": "2024-01-01T00:00:00.000Z"
}
]
}

Create DM Channel

POST /users/me/channels

Request Body:

{
"recipients": ["user_uuid1", "user_uuid2"]
}

Server Members

Get Server Members

GET /servers/:serverId/members?limit=50&after=user_uuid&query=username

Query Parameters:

  • limit: Number of members (1-1000)
  • after: Get members after this user ID (for pagination)
  • query: Search by username

Response:

{
"success": true,
"data": [
{
"user": {
"id": "uuid",
"username": "username",
"avatar": "avatar_url",
"bot": false
},
"roles": ["role_uuid"],
"joinedAt": "2024-01-01T00:00:00.000Z",
"premiumSince": null,
"nickname": "Nickname",
"pending": false,
"permissions": "104324673"
}
]
}

Add Member Role

PUT /servers/:serverId/members/:userId/roles/:roleId

Requires Permission: MANAGE_ROLES

Remove Member Role

DELETE /servers/:serverId/members/:userId/roles/:roleId

Requires Permission: MANAGE_ROLES

Kick Member

DELETE /servers/:serverId/members/:userId

Requires Permission: KICK_MEMBERS

Ban Member

PUT /servers/:serverId/bans/:userId

Requires Permission: BAN_MEMBERS

Request Body:

{
"reason": "string (optional, max 512 chars)",
"deleteMessageDays": 0 // 0-7 days
}

Search Messages

GET /search/messages?query=hello&channelId=uuid&serverId=uuid&userId=uuid&limit=25

Query Parameters:

  • query: Search query (required)
  • channelId: Search in specific channel (optional)
  • serverId: Search in specific server (optional)
  • userId: Search messages from specific user (optional)
  • limit: Number of results (1-25)
  • contextSize: Number of messages around each result (0-5)

Response:

{
"success": true,
"data": {
"results": [
{
"message": {
"id": "uuid",
"channelId": "uuid",
"author": {
"id": "uuid",
"username": "username",
"avatar": "avatar_url"
},
"content": "Hello world!",
"timestamp": "2024-01-01T00:00:00.000Z"
},
"channel": {
"id": "uuid",
"name": "general",
"type": 0
},
"score": 0.95
}
],
"totalResults": 42,
"analytics": {
"totalMessages": 1000,
"matchingMessages": 42
}
}
}

Webhooks

Create Webhook

POST /channels/:channelId/webhooks

Requires Permission: MANAGE_WEBHOOKS

Request Body:

{
"name": "string (2-32 chars)",
"avatar": "file (optional)"
}

Get Channel Webhooks

GET /channels/:channelId/webhooks

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"name": "My Webhook",
"avatar": "avatar_url",
"channelId": "uuid",
"token": "webhook_token_here",
"createdAt": "2024-01-01T00:00:00.000Z"
}
]
}

Execute Webhook

POST /webhooks/:webhookId/:webhookToken

Request Body:

{
"content": "string (max 2000 chars)",
"username": "string (optional)",
"avatarUrl": "string (optional)",
"embeds": [],
"tts": false
}

Voice

Join Voice Channel

POST /voice/channels/:channelId/join

Requires Permission: CONNECT

Response:

{
"success": true,
"data": {
"token": "voice_token_here",
"endpoint": "voice-server.example.com",
"ssrc": 12345
}
}

Leave Voice Channel

POST /voice/channels/:channelId/leave

Admin Endpoints

Get Server Statistics

GET /admin/stats

Requires: Admin authentication or ADMIN_KEY

Response:

{
"success": true,
"data": {
"users": {
"total": 10000,
"activeToday": 1500,
"newThisMonth": 500
},
"servers": {
"total": 500,
"activeToday": 100
},
"messages": {
"today": 50000,
"thisWeek": 300000
},
"storage": {
"totalUsed": "10.5 GB",
"filesTotal": 50000
}
}
}

Audit Log

GET /admin/audit-log?serverId=uuid&userId=uuid&action=type&limit=50

Response:

{
"success": true,
"data": [
{
"id": "uuid",
"action": "MEMBER_BAN_ADD",
"targetId": "user_uuid",
"userId": "moderator_uuid",
"reason": "Spam in general channel",
"createdAt": "2024-01-01T00:00:00.000Z",
"options": {
"deleteMessageDays": 1
}
}
]
}

Error Codes

CodeHTTP StatusDescription
UNKNOWN_ERROR500Internal server error
VALIDATION_ERROR400Invalid input data
UNAUTHORIZED401Authentication required
FORBIDDEN403Insufficient permissions
NOT_FOUND404Resource not found
RATE_LIMITED429Too many requests
ALREADY_EXISTS409Resource already exists
BANNED403User is banned
ACCOUNT_DISABLED403Account is disabled

WebSocket Events

Connection

const ws = new WebSocket('ws://localhost:3001');

// Authenticate
ws.send(JSON.stringify({
type: 'AUTHENTICATE',
token: 'your_jwt_token_here'
}));

Events

READY

{
"type": "READY",
"data": {
"user": {
"id": "uuid",
"username": "username"
},
"servers": ["server_id"],
"session_id": "session_uuid"
}
}

MESSAGE_CREATE

{
"type": "MESSAGE_CREATE",
"data": {
"id": "uuid",
"channelId": "uuid",
"author": {
"id": "uuid",
"username": "username"
},
"content": "Hello world!",
"timestamp": "2024-01-01T00:00:00.000Z"
}
}

TYPING_START

{
"type": "TYPING_START",
"data": {
"channelId": "uuid",
"userId": "uuid",
"timestamp": 1640995200000
}
}

PRESENCE_UPDATE

{
"type": "PRESENCE_UPDATE",
"data": {
"user": {
"id": "uuid",
"username": "username"
},
"status": "online",
"activities": []
}
}

Rate Limits

Rate limits are implemented using the X-RateLimit-* headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
X-RateLimit-Bucket: bucket_identifier

When rate limited, the response includes:

{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "You are being rate limited.",
"retryAfter": 15000
}
}

SDKs and Libraries

Official SDKs

Nothing yet!


Happy Building! 🚀