Build bots, automate messaging, and integrate OSHI into your applications
The OSHI Bot API lets you create bots that can send messages to groups and channels, similar to Telegram's Bot API. Bots are created from the OSHI app and controlled programmatically via HTTP endpoints.
Create bots directly from the OSHI app with a Telegram BotFather-like wizard
Each bot gets a unique token for secure API access
Simple REST API - send messages from any language with a single POST request
Official Python SDK with OshiBot class for quick integration
Keyword, command, schedule, and webhook triggers built-in
Bridge class for MoltBot framework integration
Follow these 4 steps to create a bot and start sending messages:
Open OSHI app > Portal > Bots > tap "+" to create a new bot
After creation, copy the bot token shown on the success screen
Add the bot to a group from Bot Settings > Assigned Groups
Use the API, Python SDK, or curl to send messages via your token
https://oshi-messenger.com
Your bot token grants full access to send messages. Never share it publicly or commit it to version control.
/api/bot/send
Send a message to a group via bot token. This is the primary endpoint for bot messaging.
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | Yes | Bot token from OSHI app |
| groupId | string | Yes | UUID of the target group. Find it in OSHI App → Group → Info → Group ID (tap to copy) |
| content | string | Conditional | Message text or caption. Required unless mediaData is provided. |
| mediaType | string | No | Media type: photo, video, audio, or document |
| mediaData | string | No | Base64-encoded file data (max 10 MB raw size) |
| mediaFileName | string | No | Original filename (e.g., report.pdf). Required when mediaData is provided. |
curlcurl -X POST https://oshi-messenger.com/api/bot/send \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_BOT_TOKEN",
"groupId": "GROUP_UUID",
"content": "Hello from my bot"
}'
{
"success": true,
"delivered": 3,
"totalMembers": 3,
"messageId": "67a37679-9cc7-4d78-bdf9-ffadcb6fa0ef",
"groupName": "My Channel",
"hasMedia": false
}/api/bot/register
Register a bot with the server. Automatically called by the OSHI app, but can also be called manually for programmatic registration.
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | Yes | Bot token |
| botName | string | Yes | Display name for the bot |
| ownerPublicKey | string | Yes | Creator's public key |
| groups | array | No | Groups to assign: [{id, name, members}] |
curlcurl -X POST https://oshi-messenger.com/api/bot/register \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_BOT_TOKEN",
"botName": "My Alert Bot",
"ownerPublicKey": "your_public_key",
"groups": [{
"id": "group-uuid",
"name": "Alerts",
"members": ["member1_key", "member2_key"]
}]
}'
/api/bot/info?token=YOUR_TOKEN
Get bot info, stats, and assigned groups.
curlcurl "https://oshi-messenger.com/api/bot/info?token=YOUR_BOT_TOKEN"
{
"success": true,
"bot": {
"botName": "My Alert Bot",
"registeredAt": "2026-02-20T03:52:44.684Z",
"groups": [
{ "id": "uuid", "name": "Alerts", "memberCount": 5 }
],
"stats": { "messagesSent": 42, "lastActivity": "2026-02-20T12:00:00Z" }
}
}/api/bot/update-groups
Update the bot's group assignments.
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | Yes | Bot token |
| groups | array | Yes | New groups: [{id, name, members}] |
/api/bot/list
List all registered bots with stats.
curlcurl https://oshi-messenger.com/api/bot/list
/api/bot/unregister?token=YOUR_TOKEN
Remove a bot from the server registry.
curlcurl -X DELETE "https://oshi-messenger.com/api/bot/unregister?token=YOUR_BOT_TOKEN"
The official Python SDK provides a clean OshiBot class for easy integration. Only requires the requests library.
bashpip install requests
# Download the SDK
curl -O https://oshi-messenger.com/sdk/oshi_bot.py
pythonfrom oshi_bot import OshiBot
# Initialize with your bot token
bot = OshiBot(token="YOUR_BOT_TOKEN")
# Send a message to a group
result = bot.send("GROUP_UUID", "Hello from Python!")
print(f"Delivered to {result['delivered']} members")
# Get bot info
info = bot.info()
print(f"Bot: {info['bot']['botName']}")
print(f"Messages sent: {info['bot']['stats']['messagesSent']}")
# Send to all assigned groups
results = bot.send_to_all_groups("Broadcast message!")
# Get groups list
groups = bot.get_groups()
for g in groups:
print(f" {g['name']} ({g['memberCount']} members)")
python# Send an image with caption
bot.send_image("GROUP_UUID", "/path/to/chart.png", caption="Daily chart")
# Send a document
bot.send_document("GROUP_UUID", "/path/to/report.pdf", caption="Q4 Report")
# Send any file (auto-detects type from extension)
bot.send_file("GROUP_UUID", "/path/to/data.csv")
# Low-level: send raw base64 media
import base64
with open("photo.jpg", "rb") as f:
data = base64.b64encode(f.read()).decode()
bot.send_media("GROUP_UUID", "photo", data, "photo.jpg", content="Check this!")
bash# Send a message
python oshi_bot.py send YOUR_TOKEN GROUP_ID "Hello!"
# Get bot info
python oshi_bot.py info YOUR_TOKEN
# List groups
python oshi_bot.py groups YOUR_TOKEN
# Check stats
python oshi_bot.py stats YOUR_TOKEN
# List all bots on server
python oshi_bot.py list
pythonimport requests
response = requests.post("https://oshi-messenger.com/api/bot/send", json={
"token": "YOUR_BOT_TOKEN",
"groupId": "550e8400-e29b-41d4-a716-446655440000",
"content": "Market update: BTC +2.5% today"
})
data = response.json()
if data["success"]:
print(f"Delivered to {data['delivered']} members")
else:
print(f"Error: {data.get('error')}")
pythonfrom oshi_bot import OshiBot
import schedule, time
bot = OshiBot(token="YOUR_BOT_TOKEN")
GROUP = "your-group-uuid"
def send_daily_report():
report = generate_report() # your logic
bot.send(GROUP, f"Daily Report\n{report}")
schedule.every().day.at("09:00").do(send_daily_report)
while True:
schedule.run_pending()
time.sleep(60)
pythonimport base64, requests
# --- Send a photo ---
with open("chart.png", "rb") as f:
img_b64 = base64.b64encode(f.read()).decode()
requests.post("https://oshi-messenger.com/api/bot/send", json={
"token": "YOUR_BOT_TOKEN",
"groupId": "GROUP_UUID",
"content": "Daily chart",
"mediaType": "photo",
"mediaData": img_b64,
"mediaFileName": "chart.png"
})
# --- Send a document ---
with open("report.pdf", "rb") as f:
doc_b64 = base64.b64encode(f.read()).decode()
requests.post("https://oshi-messenger.com/api/bot/send", json={
"token": "YOUR_BOT_TOKEN",
"groupId": "GROUP_UUID",
"content": "Monthly report",
"mediaType": "document",
"mediaData": doc_b64,
"mediaFileName": "report.pdf"
})
bashcurl -X POST https://oshi-messenger.com/api/bot/send \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_BOT_TOKEN",
"groupId": "GROUP_UUID",
"content": "Hello from curl"
}'
bashcurl -X POST https://oshi-messenger.com/api/bot/register \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_BOT_TOKEN",
"botName": "My Bot",
"ownerPublicKey": "your_public_key",
"groups": []
}'
bashcurl "https://oshi-messenger.com/api/bot/info?token=YOUR_BOT_TOKEN"
bash# Encode file and send as media
FILE_B64=$(base64 -i chart.png)
curl -X POST https://oshi-messenger.com/api/bot/send \
-H "Content-Type: application/json" \
-d "{
\"token\": \"YOUR_BOT_TOKEN\",
\"groupId\": \"GROUP_UUID\",
\"content\": \"Daily chart\",
\"mediaType\": \"photo\",
\"mediaData\": \"$FILE_B64\",
\"mediaFileName\": \"chart.png\"
}"
javascript// Send a message with fetch
const response = await fetch("https://oshi-messenger.com/api/bot/send", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: "YOUR_BOT_TOKEN",
groupId: "GROUP_UUID",
content: "Hello from JavaScript!"
})
});
const data = await response.json();
console.log(`Delivered to ${data.delivered} members`);
javascriptconst axios = require("axios");
const { data } = await axios.post("https://oshi-messenger.com/api/bot/send", {
token: "YOUR_BOT_TOKEN",
groupId: "GROUP_UUID",
content: "Hello from Node.js!"
});
console.log(data);
javascriptconst fs = require("fs");
const fileData = fs.readFileSync("report.pdf").toString("base64");
const response = await fetch("https://oshi-messenger.com/api/bot/send", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: "YOUR_BOT_TOKEN",
groupId: "GROUP_UUID",
content: "Monthly report",
mediaType: "document",
mediaData: fileData,
mediaFileName: "report.pdf"
})
});
gopackage main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
payload, _ := json.Marshal(map[string]string{
"token": "YOUR_BOT_TOKEN",
"groupId": "GROUP_UUID",
"content": "Hello from Go!",
})
resp, err := http.Post(
"https://oshi-messenger.com/api/bot/send",
"application/json",
bytes.NewBuffer(payload),
)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Printf("Delivered: %v\n", result["delivered"])
}
gofileBytes, _ := os.ReadFile("report.pdf")
fileB64 := base64.StdEncoding.EncodeToString(fileBytes)
payload, _ := json.Marshal(map[string]string{
"token": "YOUR_BOT_TOKEN",
"groupId": "GROUP_UUID",
"content": "Monthly report",
"mediaType": "document",
"mediaData": fileB64,
"mediaFileName": "report.pdf",
})
resp, _ := http.Post(
"https://oshi-messenger.com/api/bot/send",
"application/json",
bytes.NewBuffer(payload),
)
Bots can send images, videos, audio, and documents alongside text messages. Media is sent as Base64-encoded data within the JSON payload.
| Type | Value | Extensions | Max Size |
|---|---|---|---|
| photo | "photo" | PNG, JPG, GIF, WebP, HEIC | 10 MB |
| video | "video" | MP4, MOV, AVI | 10 MB |
| audio | "audio" | MP3, M4A, WAV, OGG | 10 MB |
| document | "document" | PDF, TXT, DOCX, CSV, any | 10 MB |
Media data is limited to 10 MB (raw file size, before Base64 encoding). The total request body limit is 15 MB to accommodate Base64 overhead (~33%).
mediaType, mediaData, and mediaFileName in the request bodycontent field serves as an optional captionAll messages in OSHI benefit from the same encryption pipeline used for user messages. Bot messages are encrypted before being stored on IPFS.
/api/bot/sendMessages stored on IPFS are wrapped in an encrypted envelope. Only the version number and a short routing hint are visible:
{
"v": 2,
"envelope": "aGVsbG8gd29ybGQ...",
"hint": "a1b2",
"nonce": "dW5pcXVlbm9uY2U..."
}Hidden inside the encrypted envelope:
The OSHI SDK includes an OshiMoltBotBridge class that acts as a transport/output plugin for the MoltBot multi-platform bot framework.
pythonfrom oshi_bot import OshiMoltBotBridge
# Initialize bridge
bridge = OshiMoltBotBridge(
oshi_token="YOUR_BOT_TOKEN",
default_group="GROUP_UUID"
)
# Send to default group
bridge.send("Hello from MoltBot!")
# Send to specific group
bridge.send("Alert!", group_id="other-group-uuid")
# Broadcast to all groups
bridge.broadcast("System maintenance in 5 minutes")
# Use as MoltBot output plugin
class MyMoltBot:
def __init__(self):
self.outputs = [bridge]
def on_event(self, event):
message = f"Event: {event['type']} - {event['data']}"
for output in self.outputs:
output.send(message)
OSHI supports 4 bot types, each designed for different use cases:
Responds to keyword/command triggers in group messages
Receives events via HTTP POST from external services
Sends messages on a timer (daily reports, reminders)
Welcome messages, rules enforcement, group management
| Limit | Value | Description |
|---|---|---|
| Messages/minute | 60 | Per bot token, sliding window |
| Request body | 15 MB | Max JSON payload size (includes Base64-encoded media) |
| Media file | 10 MB | Max raw file size per media attachment |
| Content length | No limit | Message content has no character limit |
The Python SDK automatically retries once after a 5-second wait when rate limited. Set auto_retry=False to disable.
| HTTP Code | Error | Cause |
|---|---|---|
| 400 | Bad Request | Missing required fields (token, groupId) or missing both content and mediaData |
| 401 | Unauthorized | Invalid bot token. Register the bot first. |
| 403 | Forbidden | Bot not assigned to this group |
| 404 | Not Found | Bot not found (for info/unregister) |
| 429 | Too Many Requests | Rate limit exceeded (60/min) |
pythonfrom oshi_bot import OshiBot, OshiAuthError, OshiGroupError, OshiRateLimitError
bot = OshiBot(token="YOUR_TOKEN")
try:
bot.send("GROUP_ID", "Hello!")
except OshiAuthError:
print("Invalid token - register the bot first")
except OshiGroupError:
print("Bot not assigned to this group")
except OshiRateLimitError:
print("Slow down - rate limit exceeded")