API Examples
This section provides practical examples of using the BotServer REST API in various programming languages and scenarios.
Authentication Examples
Getting a Session Token
JavaScript/TypeScript:
// Note: Authentication is handled through Zitadel OAuth flow
// This is a simplified example
async function authenticate() {
// Redirect to Zitadel login
window.location.href = '/auth/login';
// After OAuth callback, session token is set
// Use it for subsequent requests
}
cURL:
# Session validation
curl -X GET http://localhost:8080/auth/validate \
-H "Authorization: Bearer YOUR_SESSION_TOKEN"
Group Management Examples
Creating a Group
JavaScript:
async function createGroup() {
const response = await fetch('/api/groups/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
},
body: JSON.stringify({
name: 'Engineering Team',
description: 'Software developers'
})
});
const group = await response.json();
console.log('Created group:', group);
}
Python:
import requests
def create_group():
url = "http://localhost:8080/api/groups/create"
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
}
data = {
"name": "Engineering Team",
"description": "Software developers"
}
response = requests.post(url, json=data, headers=headers)
return response.json()
Adding Group Members
JavaScript:
async function addMember(groupId, userId) {
const response = await fetch(`/api/groups/${groupId}/members/add`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
},
body: JSON.stringify({
user_id: userId,
role: 'member'
})
});
return response.json();
}
Admin API Examples
Getting System Status
cURL:
curl -X GET http://localhost:8080/api/admin/system/status \
-H "Authorization: Bearer ADMIN_TOKEN"
Go:
package main
import (
"net/http"
"io/ioutil"
"fmt"
)
func getSystemStatus(token string) {
client := &http.Client{}
req, _ := http.NewRequest("GET",
"http://localhost:8080/api/admin/system/status", nil)
req.Header.Add("Authorization", "Bearer " + token)
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
Creating a Backup
JavaScript:
async function createBackup() {
const response = await fetch('/api/admin/backup/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ADMIN_TOKEN'
},
body: JSON.stringify({
backup_type: 'full',
include_data: true,
include_config: true
})
});
const backup = await response.json();
console.log('Backup created:', backup.id);
console.log('Download URL:', backup.download_url);
}
WebSocket Communication
Real-Time Chat
JavaScript:
class BotChat {
constructor(sessionId) {
this.sessionId = sessionId;
this.ws = null;
}
connect() {
this.ws = new WebSocket('ws://localhost:8080/ws');
this.ws.onopen = () => {
console.log('Connected to bot');
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
}
sendMessage(content) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({
type: 'message',
content: content,
session_id: this.sessionId
}));
}
}
handleMessage(message) {
console.log('Bot response:', message.content);
if (message.suggestions) {
console.log('Suggestions:', message.suggestions);
}
}
}
// Usage
const chat = new BotChat('session-123');
chat.connect();
chat.sendMessage('Hello bot!');
Error Handling
Handling API Errors
JavaScript:
async function apiCall(url, options = {}) {
try {
const response = await fetch(url, {
...options,
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || `HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('API Error:', error);
// Handle specific error codes
if (error.code === 'RATE_LIMITED') {
// Wait and retry
await new Promise(resolve => setTimeout(resolve, 1000));
return apiCall(url, options);
}
throw error;
}
}
Rate Limit Handling
Python:
import time
import requests
class APIClient:
def __init__(self, base_url, token):
self.base_url = base_url
self.headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
def request(self, method, endpoint, **kwargs):
url = f"{self.base_url}{endpoint}"
response = requests.request(
method, url,
headers=self.headers,
**kwargs
)
# Check rate limit headers
remaining = response.headers.get('X-RateLimit-Remaining')
if remaining and int(remaining) < 10:
reset_time = int(response.headers.get('X-RateLimit-Reset', 0))
sleep_time = max(reset_time - time.time(), 0)
print(f"Rate limit approaching, sleeping {sleep_time}s")
time.sleep(sleep_time)
response.raise_for_status()
return response.json()
Pagination Examples
Iterating Through Paginated Results
JavaScript:
async function* getAllGroups(token) {
let offset = 0;
const limit = 20;
while (true) {
const response = await fetch(
`/api/groups/list?limit=${limit}&offset=${offset}`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
);
const data = await response.json();
for (const group of data.groups) {
yield group;
}
if (data.groups.length < limit) {
break; // No more pages
}
offset += limit;
}
}
// Usage
for await (const group of getAllGroups(token)) {
console.log(group.name);
}
Integration Patterns
Webhook Handler
Node.js/Express:
const express = require('express');
const app = express();
app.post('/webhook/botserver', express.json(), (req, res) => {
const event = req.body;
switch(event.type) {
case 'user.created':
handleUserCreated(event.data);
break;
case 'conversation.completed':
handleConversationCompleted(event.data);
break;
default:
console.log('Unknown event type:', event.type);
}
res.status(200).send('OK');
});
function handleUserCreated(userData) {
console.log('New user:', userData);
// Process new user
}
function handleConversationCompleted(conversationData) {
console.log('Conversation completed:', conversationData);
// Process completed conversation
}
Best Practices
- Always handle errors gracefully - Network failures happen
- Respect rate limits - Implement exponential backoff
- Use environment variables for API tokens
- Log API interactions for debugging
- Cache responses when appropriate
- Use connection pooling for multiple requests
- Implement timeout handling for long operations
Testing API Calls
Using Postman
- Import the API collection (when available)
- Set environment variables for:
base_url: http://localhost:8080token: Your session token
- Run requests individually or as collection
Unit Testing API Calls
JavaScript/Jest:
describe('Groups API', () => {
test('should create a group', async () => {
const mockFetch = jest.fn(() =>
Promise.resolve({
ok: true,
json: () => Promise.resolve({
id: 'group-123',
name: 'Test Group'
})
})
);
global.fetch = mockFetch;
const result = await createGroup('Test Group');
expect(mockFetch).toHaveBeenCalledWith(
'/api/groups/create',
expect.objectContaining({
method: 'POST'
})
);
expect(result.id).toBe('group-123');
});
});
Summary
These examples demonstrate common patterns for interacting with the BotServer API. Remember to:
- Handle authentication properly through Zitadel
- Check response status codes
- Parse error responses
- Implement proper error handling
- Use appropriate HTTP methods
- Follow REST conventions
For more specific endpoint documentation, refer to the individual API sections in this chapter.