The OneStack REST API provides complete programmatic access to all server features. This documentation is intended for developers building extensions, integrations, or custom modules.
Base URL: http://localhost:3000/api
Authentication: Basic HTTP Authentication
- Default username:
admin - Default password:
admin123
Content-Type: application/json
All API requests require HTTP Basic Authentication:
# Using curl
curl -u admin:admin123 http://localhost:3000/api/status
# Using Authorization header
curl -H "Authorization: Basic YWRtaW46YWRtaW4xMjM=" http://localhost:3000/api/status{
"data": { ... },
"success": true
}{
"error": "Error message",
"code": "ERROR_CODE",
"details": { ... }
}200- Success201- Created400- Bad Request401- Unauthorized403- Forbidden404- Not Found500- Internal Server Error503- Service Unavailable (module not running)
Returns complete server status including all modules, memory usage, and uptime.
Endpoint: GET /api/status
Response:
{
"uptime": 3600,
"memory": {
"heapUsed": 50000000,
"heapTotal": 100000000,
"external": 1000000,
"rss": 120000000
},
"modules": {
"http": {
"running": true,
"workers": 4,
"customThreads": 0,
"config": { "port": 8080, "enabled": true }
},
"email": {
"running": true,
"workers": 2,
"customThreads": 0,
"config": { "smtp": { "port": 2525 }, "imap": { "port": 1143 } }
}
}
}Simple health check endpoint.
Endpoint: GET /api/health
Response:
{
"status": "healthy",
"timestamp": "2025-10-13T10:30:00.000Z"
}Get current server configuration.
Endpoint: GET /api/config
Response:
{
"server": {
"adminPanel": {
"enabled": true,
"port": 3000,
"username": "admin",
"password": "admin123"
}
},
"modules": {
"http": { "enabled": true, "port": 8080 },
"email": { "enabled": true, "smtp": { "port": 2525 } }
}
}Update server configuration. Partial updates supported.
Endpoint: PUT /api/config
Request Body:
{
"modules": {
"http": {
"port": 8081
}
}
}Response:
{
"success": true,
"config": { ... }
}Reload configuration from file.
Endpoint: POST /api/config/reload
Response:
{
"success": true,
"config": { ... }
}Reset to default configuration.
Endpoint: POST /api/config/reset
Response:
{
"success": true,
"config": { ... }
}Export configuration as JSON file.
Endpoint: GET /api/config/export
Response: JSON file download
Import configuration from uploaded file.
Endpoint: POST /api/config/import
Request: multipart/form-data with file
Response:
{
"success": true,
"config": { ... }
}Get list of all available modules.
Endpoint: GET /api/modules
Response:
{
"modules": ["http", "https", "dns", "email", "ssh"]
}Get status of a specific module.
Endpoint: GET /api/modules/:name
Response:
{
"name": "http",
"running": true,
"workers": 4,
"customThreads": 0,
"config": {
"enabled": true,
"port": 8080,
"host": "0.0.0.0"
}
}Start a specific module.
Endpoint: POST /api/modules/:name/start
Response:
{
"success": true,
"module": "http",
"status": "running"
}Stop a specific module.
Endpoint: POST /api/modules/:name/stop
Response:
{
"success": true,
"module": "http",
"status": "stopped"
}Reload a specific module (stop and start).
Endpoint: POST /api/modules/:name/reload
Response:
{
"success": true,
"module": "http",
"status": "running"
}Update module-specific configuration.
Endpoint: PUT /api/modules/:name/config
Request Body:
{
"port": 8081,
"enabled": true
}Response:
{
"success": true,
"config": { ... }
}Get all virtual hosts.
Endpoint: GET /api/vhosts
Response:
[
{
"id": 1,
"domain": "example.com",
"aliases": ["www.example.com"],
"documentRoot": "/path/to/site",
"enabled": true,
"ssl": false,
"redirectToHttps": false,
"stats": {
"requests": 1234,
"bytesServed": 567890,
"lastRequest": "2025-10-13T10:30:00.000Z"
}
}
]Get specific virtual host by ID.
Endpoint: GET /api/vhosts/:id
Response:
{
"id": 1,
"domain": "example.com",
"aliases": ["www.example.com"],
"documentRoot": "/path/to/site",
"enabled": true
}Create a new virtual host.
Endpoint: POST /api/vhosts
Request Body:
{
"domain": "example.com",
"aliases": ["www.example.com", "blog.example.com"],
"documentRoot": "/optional/custom/path",
"enabled": true,
"ssl": false,
"redirectToHttps": false
}Response:
{
"id": 1,
"domain": "example.com",
"documentRoot": "/auto/generated/path",
"enabled": true
}Update existing virtual host.
Endpoint: PUT /api/vhosts/:id
Request Body:
{
"enabled": false,
"aliases": ["www.example.com"]
}Response:
{
"success": true,
"vhost": { ... }
}Delete virtual host.
Endpoint: DELETE /api/vhosts/:id?deleteFiles=true
Query Parameters:
deleteFiles(boolean) - Also delete files from filesystem
Response:
{
"success": true
}Get detailed statistics for a virtual host.
Endpoint: GET /api/vhosts/:id/stats
Response:
{
"requests": 1234,
"bytesServed": 567890,
"lastRequest": "2025-10-13T10:30:00.000Z",
"averageResponseTime": 45
}Get all DNS zones.
Endpoint: GET /api/dns/zones
Response:
[
{
"name": "example.com",
"enabled": true,
"ttl": 3600,
"soa": {
"primaryNS": "ns1.example.com",
"email": "admin.example.com",
"serial": 2025101301,
"refresh": 3600,
"retry": 1800,
"expire": 604800,
"minimum": 86400
},
"records": [
{
"id": 1,
"name": "@",
"type": "A",
"data": "192.168.1.1",
"ttl": 300
}
]
}
]Get specific DNS zone.
Endpoint: GET /api/dns/zones/:name
Response:
{
"name": "example.com",
"enabled": true,
"records": [ ... ]
}Create new DNS zone.
Endpoint: POST /api/dns/zones
Request Body:
{
"name": "example.com",
"options": {
"enabled": true,
"ttl": 3600,
"primaryNS": "ns1.example.com",
"email": "admin.example.com"
}
}Response:
{
"name": "example.com",
"enabled": true,
"soa": { ... }
}Update DNS zone settings.
Endpoint: PUT /api/dns/zones/:name
Request Body:
{
"enabled": true,
"ttl": 7200
}Response:
{
"success": true,
"zone": { ... }
}Delete DNS zone.
Endpoint: DELETE /api/dns/zones/:name
Response:
{
"success": true
}Get all records for a zone.
Endpoint: GET /api/dns/zones/:name/records
Response:
[
{
"id": 1,
"name": "www",
"type": "A",
"data": "192.168.1.1",
"ttl": 300
}
]Add record to zone.
Endpoint: POST /api/dns/zones/:name/records
Request Body:
{
"name": "www",
"type": "A",
"data": "192.168.1.1",
"ttl": 300,
"priority": 10
}Supported Record Types:
A- IPv4 addressAAAA- IPv6 addressCNAME- Canonical nameMX- Mail exchange (requirespriority)TXT- Text recordNS- NameserverSRV- Service recordPTR- Pointer recordCAA- Certificate authority
Response:
{
"id": 1,
"name": "www",
"type": "A",
"data": "192.168.1.1"
}Update existing record.
Endpoint: PUT /api/dns/records/:id
Request Body:
{
"data": "192.168.1.100",
"ttl": 600
}Response:
{
"success": true,
"record": { ... }
}Delete DNS record.
Endpoint: DELETE /api/dns/records/:id
Response:
{
"success": true
}Export zone in BIND format.
Endpoint: GET /api/dns/zones/:name/export
Response: Text file in BIND format
Import zone from BIND format.
Endpoint: POST /api/dns/zones/:name/import
Request Body:
{
"zoneFile": "$ORIGIN example.com.\n$TTL 3600\n@ IN SOA ..."
}Response:
{
"success": true,
"recordsImported": 10
}Get all mailboxes.
Endpoint: GET /api/mailboxes
Response:
[
{
"id": 1,
"email": "user@example.com",
"name": "User Name",
"quota": 104857600,
"quotaUsed": 12345,
"created": "2025-10-13T10:30:00.000Z",
"enabled": true,
"messageCount": 5,
"unreadCount": 2
}
]Get specific mailbox.
Endpoint: GET /api/mailboxes/:email
Response:
{
"id": 1,
"email": "user@example.com",
"name": "User Name",
"quota": 104857600,
"enabled": true
}Create new mailbox.
Endpoint: POST /api/mailboxes
Request Body:
{
"email": "user@example.com",
"name": "User Name",
"password": "optional_password",
"quota": 104857600,
"enabled": true
}Note: If password is omitted, one will be auto-generated.
Response:
{
"id": 1,
"email": "user@example.com",
"password": "a3f8d92c1e6b4759",
"name": "User Name",
"enabled": true
}Update mailbox settings.
Endpoint: PUT /api/mailboxes/:email
Request Body:
{
"enabled": false,
"quota": 209715200,
"password": "newpassword"
}Response:
{
"success": true,
"mailbox": { ... }
}Delete mailbox.
Endpoint: DELETE /api/mailboxes/:email?deleteMessages=true
Query Parameters:
deleteMessages(boolean) - Also delete all messages
Response:
{
"success": true
}Get mailbox statistics.
Endpoint: GET /api/mailboxes/:email/stats
Response:
{
"email": "user@example.com",
"messageCount": 5,
"unreadCount": 2,
"quotaUsed": 12345,
"quota": 104857600,
"quotaPercentage": 12,
"enabled": true,
"created": "2025-10-13T10:30:00.000Z"
}Get messages for mailbox.
Endpoint: GET /api/mailboxes/:email/messages
Query Parameters:
folder(string) - Filter by folder (inbox, sent, trash)unreadOnly(boolean) - Show only unread messageslimit(number) - Max messages to returnoffset(number) - Offset for pagination
Example: GET /api/mailboxes/user@example.com/messages?folder=inbox&limit=50&offset=0
Response:
[
{
"id": 1,
"messageId": "<unique@onestack>",
"from": "sender@example.com",
"to": "user@example.com",
"subject": "Test Email",
"body": "Message body...",
"date": "2025-10-13T10:30:00.000Z",
"read": false,
"flagged": false,
"folder": "inbox",
"size": 1234
}
]Get specific message by ID.
Endpoint: GET /api/messages/:id
Response:
{
"id": 1,
"from": "sender@example.com",
"to": "recipient@example.com",
"subject": "Test Email",
"body": "Full message body...",
"html": "<p>HTML version...</p>",
"headers": { ... },
"date": "2025-10-13T10:30:00.000Z",
"read": false
}Mark message as read or unread.
Endpoint: PUT /api/messages/:id/read
Request Body:
{
"read": true
}Response:
{
"success": true,
"message": { ... }
}Delete a message.
Endpoint: DELETE /api/messages/:id
Response:
{
"success": true
}Move message to different folder.
Endpoint: PUT /api/messages/:id/move
Request Body:
{
"folder": "trash"
}Response:
{
"success": true,
"message": { ... }
}Send a new email.
Endpoint: POST /api/send-email
Request Body:
{
"from": "sender@example.com",
"to": "recipient@example.com",
"subject": "Test Email",
"body": "Plain text body",
"html": "<p>HTML body</p>",
"headers": {
"X-Custom-Header": "value"
}
}Response:
{
"success": true,
"message": {
"id": 1,
"messageId": "<unique@onestack>"
}
}Get email module statistics.
Endpoint: GET /api/email/stats
Response:
{
"messagesSent": 100,
"messagesReceived": 150,
"smtpConnections": 50,
"imapConnections": 30,
"mailboxCount": 5,
"totalMessages": 250,
"totalStorage": 12345678,
"activeMailboxes": 4
}The admin panel uses WebSocket for real-time updates. You can also connect to receive live events.
Endpoint: ws://localhost:3000
Authentication: Send credentials in connection URL or initial message
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = () => {
console.log('Connected');
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};Sent every 5 seconds with current status.
{
"type": "status",
"data": {
"uptime": 3600,
"memory": { ... },
"modules": { ... }
}
}{
"type": "configUpdated",
"data": { ... }
}{
"type": "moduleStarted",
"data": {
"module": "http",
"status": "running"
}
}{
"type": "vhostCreated",
"data": {
"id": 1,
"domain": "example.com"
}
}{
"type": "vhostUpdated",
"data": { ... }
}{
"type": "vhostDeleted",
"data": {
"id": 1
}
}{
"type": "dnsZoneCreated",
"data": {
"name": "example.com"
}
}{
"type": "dnsRecordAdded",
"data": {
"zone": "example.com",
"record": { ... }
}
}{
"type": "mailboxCreated",
"data": {
"email": "user@example.com"
}
}{
"type": "emailSent",
"data": {
"from": "sender@example.com",
"to": "recipient@example.com"
}
}{
"type": "messageUpdated",
"data": {
"id": 1,
"read": true
}
}Currently no rate limiting is implemented. For production:
- Implement rate limiting middleware
- Track requests per IP/user
- Return
429 Too Many Requestswhen exceeded - Include
Retry-Afterheader
| Code | Description |
|---|---|
INVALID_REQUEST |
Malformed request |
AUTH_REQUIRED |
Authentication required |
AUTH_FAILED |
Invalid credentials |
NOT_FOUND |
Resource not found |
ALREADY_EXISTS |
Resource already exists |
MODULE_NOT_RUNNING |
Module not running |
INVALID_CONFIG |
Invalid configuration |
OPERATION_FAILED |
Operation failed |
class OneStackClient {
constructor(baseUrl, username, password) {
this.baseUrl = baseUrl;
this.auth = Buffer.from(`${username}:${password}`).toString('base64');
}
async request(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
'Authorization': `Basic ${this.auth}`,
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
return response.json();
}
// Virtual Hosts
async listVirtualHosts() {
return this.request('/api/vhosts');
}
async createVirtualHost(data) {
return this.request('/api/vhosts', {
method: 'POST',
body: JSON.stringify(data)
});
}
// DNS
async createDNSZone(name, options) {
return this.request('/api/dns/zones', {
method: 'POST',
body: JSON.stringify({ name, options })
});
}
async addDNSRecord(zone, record) {
return this.request(`/api/dns/zones/${zone}/records`, {
method: 'POST',
body: JSON.stringify(record)
});
}
// Email
async createMailbox(email, options) {
return this.request('/api/mailboxes', {
method: 'POST',
body: JSON.stringify({ email, ...options })
});
}
async sendEmail(from, to, subject, body) {
return this.request('/api/send-email', {
method: 'POST',
body: JSON.stringify({ from, to, subject, body })
});
}
}
// Usage
const client = new OneStackClient('http://localhost:3000', 'admin', 'admin123');
// Create virtual host
await client.createVirtualHost({
domain: 'api-test.local',
enabled: true
});
// Create mailbox
const mailbox = await client.createMailbox('api@example.com', {
name: 'API User',
quota: 104857600
});
// Send email
await client.sendEmail(
'api@example.com',
'user@example.com',
'Test from SDK',
'This email was sent via SDK'
);import requests
from requests.auth import HTTPBasicAuth
class OneStackClient:
def __init__(self, base_url, username, password):
self.base_url = base_url
self.auth = HTTPBasicAuth(username, password)
def request(self, endpoint, method='GET', json=None):
url = f"{self.base_url}{endpoint}"
response = requests.request(
method, url,
auth=self.auth,
json=json,
headers={'Content-Type': 'application/json'}
)
response.raise_for_status()
return response.json()
def list_virtual_hosts(self):
return self.request('/api/vhosts')
def create_virtual_host(self, domain, **kwargs):
data = {'domain': domain, **kwargs}
return self.request('/api/vhosts', 'POST', data)
def create_mailbox(self, email, **kwargs):
data = {'email': email, **kwargs}
return self.request('/api/mailboxes', 'POST', data)
def send_email(self, from_addr, to_addr, subject, body):
data = {
'from': from_addr,
'to': to_addr,
'subject': subject,
'body': body
}
return self.request('/api/send-email', 'POST', data)
# Usage
client = OneStackClient('http://localhost:3000', 'admin', 'admin123')
# Create virtual host
client.create_virtual_host('python-test.local', enabled=True)
# Create mailbox and send email
mailbox = client.create_mailbox('python@example.com', quota=104857600)
client.send_email(
'python@example.com',
'user@example.com',
'Test from Python',
'This email was sent via Python SDK'
)<?php
class OneStackClient {
private $baseUrl;
private $auth;
public function __construct($baseUrl, $username, $password) {
$this->baseUrl = $baseUrl;
$this->auth = base64_encode("$username:$password");
}
private function request($endpoint, $method = 'GET', $data = null) {
$url = $this->baseUrl . $endpoint;
$headers = [
"Authorization: Basic {$this->auth}",
'Content-Type: application/json'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
throw new Exception("API Error: $response");
}
return json_decode($response, true);
}
public function listVirtualHosts() {
return $this->request('/api/vhosts');
}
public function createVirtualHost($domain, $options = []) {
$data = array_merge(['domain' => $domain], $options);
return $this->request('/api/vhosts', 'POST', $data);
}
public function createMailbox($email, $options = []) {
$data = array_merge(['email' => $email], $options);
return $this->request('/api/mailboxes', 'POST', $data);
}
public function sendEmail($from, $to, $subject, $body) {
$data = [
'from' => $from,
'to' => $to,
'subject' => $subject,
'body' => $body
];
return $this->request('/api/send-email', 'POST', $data);
}
}
// Usage
$client = new OneStackClient('http://localhost:3000', 'admin', 'admin123');
// Create virtual host
$client->createVirtualHost('php-test.local', ['enabled' => true]);
// Create mailbox and send email
$mailbox = $client->createMailbox('php@example.com', ['quota' => 104857600]);
$client->sendEmail(
'php@example.com',
'user@example.com',
'Test from PHP',
'This email was sent via PHP SDK'
);
?>- Never hardcode credentials
- Use environment variables
- Rotate passwords regularly
- Use HTTPS in production
try {
const result = await client.createVirtualHost({ domain: 'test.local' });
} catch (error) {
if (error.code === 'ALREADY_EXISTS') {
console.log('Virtual host already exists');
} else {
console.error('Failed to create virtual host:', error.message);
}
}- Implement exponential backoff
- Cache responses when appropriate
- Use WebSocket for real-time data
- Validate all inputs before sending
- Check response status codes
- Handle edge cases
// Test connection
const health = await client.request('/api/health');
console.log('Server is healthy:', health.status === 'healthy');
// Test module availability
const status = await client.request('/api/status');
console.log('Email module running:', status.modules.email.running);- Check if server is running
- Verify port number (default 3000)
- Check firewall settings
- Verify username/password
- Check Authorization header format
- Ensure credentials are base64 encoded
- Check module status in admin panel
- Start module via API or UI
- Review server logs
- Module is not running
- Start module first:
POST /api/modules/email/start
- Initial API release
- Server management endpoints
- Configuration management
- Module control
- Virtual host management
- DNS zone management
- Email management
- WebSocket support
For API support:
- Review this documentation
- Check server logs
- Test with curl/Postman
- Report issues with request/response details
OneStack REST API - Part of OneStack Server Copyright © 2025