Build on Echoed
Full REST API with 40+ endpoints, real-time WebSocket events, and OAuth2 integration. Build bots that manage servers, automate tasks, send messages, and more.
Introduction
The Echoed Bot API lets you build bots that interact with servers, channels, members, messages, tasks, and calendar events. Bots authenticate with a simple token and can access any server they've been invited to.
Quick Start
- Create a bot account in your Settings → Bot Profile
- Copy your Bot API Key (starts with
zbot_) - Invite your bot to a server via the Bot Discovery page or directly
- Start making API requests with the
X-Bot-Tokenheader
Authentication
All Bot API requests require the X-Bot-Token header with your bot's API key.
X-Bot-Token: zbot_your_api_key_here Content-Type: application/json
Base URL
All Bot API endpoints are prefixed with:
https://go.echoed.gg/v1/bots
For example, to validate your token: GET https://go.echoed.gg/v1/bots/validate
Error Handling
The API returns standard HTTP status codes. Error responses include a JSON body with a message field.
| Status | Meaning |
|---|---|
200 | Success |
201 | Created (new resource) |
400 | Bad Request — invalid parameters |
401 | Unauthorized — invalid or missing token |
403 | Forbidden — insufficient permissions |
404 | Not Found — resource doesn't exist |
500 | Internal Server Error |
{
"message": "Bot is not a member of this server",
"success": false
}
Bot Profile
{
"valid": true,
"bot_id": "67e537d200011f5275d2",
"message": "Bot API key is valid."
}
{
"id": "67e537d200011f5275d2",
"username": "my-awesome-bot",
"isBot": true,
"botDescription": "A helpful server bot",
"botCategory": "utility",
"isPublic": true,
"avatarUrl": "https://s3.echoed.gg/..."
}
{
"botDescription": "Updated bot description",
"botCategory": "utility",
"isPublic": true
}
Servers
{
"count": 2,
"servers": [
{
"serverId": "6894d3d90011f842607c",
"serverName": "My Server",
"serverIcon": "",
"invitedAt": "2026-01-06T13:41:44Z",
"invitedBy": "user-id"
}
]
}
{
"id": "6894d3d90011f842607c",
"name": "My Server",
"description": "A cool server",
"ownerId": "user-id",
"memberCount": 42,
"channelCount": 8,
"iconUrl": "",
"createdAt": "2025-08-07T16:27:05Z"
}
Channels
{
"channels": [
{
"id": "647a23fede03765e0348",
"name": "general",
"type": "text",
"description": "",
"createdAt": "2026-01-05T11:20:43Z"
}
],
"total": 8
}
text, video, announcement.{
"name": "bot-updates",
"type": "text",
"topic": "Automated bot announcements"
}
{
"name": "renamed-channel",
"description": "Updated description"
}
{
"channelId": "channel-id",
"categoryId": "category-id",
"position": 0
}
Categories
{
"name": "Bot Channels",
"position": 0
}
{
"categories": [
{ "categoryId": "id1", "position": 0 },
{ "categoryId": "id2", "position": 1 }
]
}
Members
| Parameter | Type | Description |
|---|---|---|
limit | integer | Max results (default 10) |
offset | integer | Pagination offset |
{
"userId": "user-id",
"serverId": "server-id",
"permissions": [
"VIEW_CHANNELS", "SEND_MESSAGES",
"READ_MESSAGE_HISTORY", "CONNECT", "SPEAK"
]
}
KICK_MEMBERS permission.{
"reason": "Optional reason"
}
BAN_MEMBERS permission.{
"reason": "Reason for ban",
"deleteMessageDays": 1
}
Roles
{
"name": "Moderator",
"color": "#FF5733",
"permissions": ["SEND_MESSAGES", "MANAGE_MESSAGES", "KICK_MEMBERS"]
}
{
"roles": ["role-id-1", "role-id-2"]
}
Messages
limit and offset query parameters.{
"channelId": "channel-id",
"content": "Hello from my bot! 🤖",
"attachmentIds": [],
"mentions": [],
"replyToId": ""
}
Sending Messages with Attachments
To send a message with file attachments, upload the file first, then reference the returned fileId in your message.
multipart/form-data with a file field. Max file size: 50 MB. Supported types: images, videos, audio, documents, archives, and code files.{
"success": true,
"fileId": "abc123",
"path": "channels/server-id/channel-id/abc123.png",
"url": "https://s3.echoed.gg/files/channels/...",
"filename": "screenshot.png",
"size": 184320,
"contentType": "image/png",
"width": 1920,
"height": 1080,
"blurhash": "U.P,rXfQkCbH"
}
width, height, and blurhash are only returned for image uploads.
{
"channelId": "channel-id",
"content": "Check out this image!",
"attachmentIds": ["abc123"],
"mentions": [],
"replyToId": ""
}
MANAGE_MESSAGES permission.{
"content": "Edited message content"
}
Direct Messages
{
"username": "target-user",
"content": "Hey! This is a DM from my bot."
}
{
"message": "DM sent successfully.",
"messageId": "message-id",
"receiverId": "user-id",
"content": "Hey! This is a DM from my bot."
}
Tasks
Manage tasks in Task-type channels. Your bot can create, update, and delete tasks for project management and automation.
{
"channelId": "task-channel-id",
"title": "Fix login bug",
"description": "Users can't login with OAuth",
"assigneeId": "user-id",
"dueDate": "2026-04-01T00:00:00Z",
"priority": "high"
}
| Field | Values |
|---|---|
priority | low, medium, high, urgent |
status | backlog, todo, in_progress, review, done |
Calendar Events
Manage events in Calendar-type channels. Create, update, and manage event participants.
{
"channelId": "calendar-channel-id",
"title": "Game Night",
"description": "Weekly gaming session",
"startTime": "2026-04-01T20:00:00Z",
"endTime": "2026-04-01T23:00:00Z",
"location": "Voice Channel #gaming",
"isAllDay": false
}
Event Participants
{ "userId": "user-id" }
{ "userId": "user-id" }
Search
| Parameter | Type | Description |
|---|---|---|
q | string | Search query (min 2 chars, required) |
channel_id | string | Filter by channel |
author_id | string | Filter by message author |
before | ISO 8601 | Messages before this date |
after | ISO 8601 | Messages after this date |
sort | string | newest (default) or oldest |
limit | integer | Max results |
offset | integer | Pagination offset |
WebSocket Events
Connect via Socket.IO to receive real-time events. Authenticate with your bot token after connecting.
Connecting
# pip install python-socketio import socketio sio = socketio.Client() sio.connect("https://socket.echoed.gg") # Authenticate after connecting sio.emit("authenticate", { "botToken": "zbot_your_token_here" })
Subscribing to Events
After authentication, subscribe to specific servers or channels:
sio.emit("subscribe", { "botToken": "zbot_your_token", "type": "server", # or "channel" "id": "server-id" })
Event Types
All events follow the pattern { type: "resource:action", data: { ... } }
| Socket Event | Types | Description |
|---|---|---|
messageEvent |
message:created, message:updated, message:deleted |
Message send, edit, delete in channels |
channelEvent |
channel:created, channel:updated, channel:deleted |
Channel CRUD operations |
categoryEvent |
category:created, category:updated, category:deleted |
Category changes |
serverEvent |
server:updated, server:member:joined, server:member:left |
Server and membership events |
taskEvent |
task:created, task:updated, task:deleted |
Task changes in task channels |
eventEvent |
event:created, event:updated, event:deleted |
Calendar event changes |
reactionEvent |
reaction:created, reaction:deleted |
Message reaction add/remove |
friendEvent |
friend:request_sent, friend:request_accepted |
Friend request events |
countEvent |
— | Unread count updates |
Message Event Payload
{
"type": "message:created",
"data": {
"id": "message-id",
"channelId": "channel-id",
"serverId": "server-id",
"senderId": "user-id",
"content": "Hello everyone!",
"messageType": "user",
"createdAt": "2026-03-14T12:00:00Z",
"author": {
"id": "user-id",
"name": "Username",
"avatarUrl": "https://..."
}
}
}
OAuth2
Integrate "Login with Echoed" into your application, access user data, and invite bots to servers using standard OAuth2 authorization code flow.
Authorization Flow
- Register an OAuth2 client in Settings → OAuth2 Apps
- Redirect users to the authorization URL with your
client_idand requested scopes - User approves — Echoed redirects back with an authorization code
- Exchange the code for access + refresh tokens
- Use the access token to call OAuth2 API endpoints
https://go.echoed.gg/oauth2/authorize? response_type=code& client_id=your_client_id& redirect_uri=https://yourapp.com/callback& scope=openid profile email servers& state=random_csrf_token
POST https://go.echoed.gg/oauth2/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& code=authorization_code_from_callback& redirect_uri=https://yourapp.com/callback& client_id=your_client_id& client_secret=your_client_secret
{
"access_token": "MKquTIm08LMU...",
"refresh_token": "dR4nG7kP...",
"expires_in": 3600,
"token_type": "Bearer"
}
Scopes
| Scope | Access |
|---|---|
openid | Basic identity (user ID, issuer) |
profile | Name, username, avatar, created date |
email | Email address |
servers | User's servers, invite bots to servers |
friends | User's friends list |
offline_access | Receive a refresh token for long-lived access |
Token Lifetimes
| Token | Lifetime |
|---|---|
| Authorization Code | 10 minutes |
| Access Token | 1 hour |
| Refresh Token | 30 days |
OAuth2 Endpoints
Bearer token in Authorization header.{
"sub": "user-id",
"name": "Display Name",
"username": "username",
"avatar_url": "https://s3.echoed.gg/...",
"email": "[email protected]",
"owned_servers": [
{ "id": "server-id", "name": "My Server", "type": "public" }
],
"servers_count": 5
}
servers scope.friends scope.servers scope and bot management permission.{ "bot_id": "bot-user-id" }
application/x-www-form-urlencoded.token=access_token_value& token_type_hint=access_token& client_id=your_client_id& client_secret=your_client_secret
offline_access only if your app needs long-lived access.