Skip to content

Latest commit

 

History

History
1428 lines (1156 loc) · 23.6 KB

File metadata and controls

1428 lines (1156 loc) · 23.6 KB

OneStack REST API Documentation

Overview

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

Authentication

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

Response Format

Success Response

{
  "data": { ... },
  "success": true
}

Error Response

{
  "error": "Error message",
  "code": "ERROR_CODE",
  "details": { ... }
}

HTTP Status Codes

  • 200 - Success
  • 201 - Created
  • 400 - Bad Request
  • 401 - Unauthorized
  • 403 - Forbidden
  • 404 - Not Found
  • 500 - Internal Server Error
  • 503 - Service Unavailable (module not running)

Server Management

Get Server Status

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 } }
    }
  }
}

Health Check

Simple health check endpoint.

Endpoint: GET /api/health

Response:

{
  "status": "healthy",
  "timestamp": "2025-10-13T10:30:00.000Z"
}

Configuration Management

Get Configuration

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 Configuration

Update server configuration. Partial updates supported.

Endpoint: PUT /api/config

Request Body:

{
  "modules": {
    "http": {
      "port": 8081
    }
  }
}

Response:

{
  "success": true,
  "config": { ... }
}

Reload Configuration

Reload configuration from file.

Endpoint: POST /api/config/reload

Response:

{
  "success": true,
  "config": { ... }
}

Reset Configuration

Reset to default configuration.

Endpoint: POST /api/config/reset

Response:

{
  "success": true,
  "config": { ... }
}

Export Configuration

Export configuration as JSON file.

Endpoint: GET /api/config/export

Response: JSON file download

Import Configuration

Import configuration from uploaded file.

Endpoint: POST /api/config/import

Request: multipart/form-data with file

Response:

{
  "success": true,
  "config": { ... }
}

Module Management

List All Modules

Get list of all available modules.

Endpoint: GET /api/modules

Response:

{
  "modules": ["http", "https", "dns", "email", "ssh"]
}

Get Module Status

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 Module

Start a specific module.

Endpoint: POST /api/modules/:name/start

Response:

{
  "success": true,
  "module": "http",
  "status": "running"
}

Stop Module

Stop a specific module.

Endpoint: POST /api/modules/:name/stop

Response:

{
  "success": true,
  "module": "http",
  "status": "stopped"
}

Reload Module

Reload a specific module (stop and start).

Endpoint: POST /api/modules/:name/reload

Response:

{
  "success": true,
  "module": "http",
  "status": "running"
}

Update Module Configuration

Update module-specific configuration.

Endpoint: PUT /api/modules/:name/config

Request Body:

{
  "port": 8081,
  "enabled": true
}

Response:

{
  "success": true,
  "config": { ... }
}

Virtual Hosts Management

List Virtual Hosts

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 Virtual Host

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 Virtual Host

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 Virtual Host

Update existing virtual host.

Endpoint: PUT /api/vhosts/:id

Request Body:

{
  "enabled": false,
  "aliases": ["www.example.com"]
}

Response:

{
  "success": true,
  "vhost": { ... }
}

Delete Virtual Host

Delete virtual host.

Endpoint: DELETE /api/vhosts/:id?deleteFiles=true

Query Parameters:

  • deleteFiles (boolean) - Also delete files from filesystem

Response:

{
  "success": true
}

Get Virtual Host Statistics

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
}

DNS Zone Management

List DNS Zones

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 DNS Zone

Get specific DNS zone.

Endpoint: GET /api/dns/zones/:name

Response:

{
  "name": "example.com",
  "enabled": true,
  "records": [ ... ]
}

Create DNS Zone

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

Update DNS zone settings.

Endpoint: PUT /api/dns/zones/:name

Request Body:

{
  "enabled": true,
  "ttl": 7200
}

Response:

{
  "success": true,
  "zone": { ... }
}

Delete DNS Zone

Delete DNS zone.

Endpoint: DELETE /api/dns/zones/:name

Response:

{
  "success": true
}

List DNS Records

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 DNS Record

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 address
  • AAAA - IPv6 address
  • CNAME - Canonical name
  • MX - Mail exchange (requires priority)
  • TXT - Text record
  • NS - Nameserver
  • SRV - Service record
  • PTR - Pointer record
  • CAA - Certificate authority

Response:

{
  "id": 1,
  "name": "www",
  "type": "A",
  "data": "192.168.1.1"
}

Update DNS Record

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

Delete DNS record.

Endpoint: DELETE /api/dns/records/:id

Response:

{
  "success": true
}

Export DNS Zone

Export zone in BIND format.

Endpoint: GET /api/dns/zones/:name/export

Response: Text file in BIND format

Import DNS Zone

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
}

Email Management

List Mailboxes

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 Mailbox

Get specific mailbox.

Endpoint: GET /api/mailboxes/:email

Response:

{
  "id": 1,
  "email": "user@example.com",
  "name": "User Name",
  "quota": 104857600,
  "enabled": true
}

Create Mailbox

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

Update mailbox settings.

Endpoint: PUT /api/mailboxes/:email

Request Body:

{
  "enabled": false,
  "quota": 209715200,
  "password": "newpassword"
}

Response:

{
  "success": true,
  "mailbox": { ... }
}

Delete Mailbox

Delete mailbox.

Endpoint: DELETE /api/mailboxes/:email?deleteMessages=true

Query Parameters:

  • deleteMessages (boolean) - Also delete all messages

Response:

{
  "success": true
}

Get Mailbox Statistics

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"
}

List Messages

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 messages
  • limit (number) - Max messages to return
  • offset (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 Message

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 Read/Unread

Mark message as read or unread.

Endpoint: PUT /api/messages/:id/read

Request Body:

{
  "read": true
}

Response:

{
  "success": true,
  "message": { ... }
}

Delete Message

Delete a message.

Endpoint: DELETE /api/messages/:id

Response:

{
  "success": true
}

Move Message

Move message to different folder.

Endpoint: PUT /api/messages/:id/move

Request Body:

{
  "folder": "trash"
}

Response:

{
  "success": true,
  "message": { ... }
}

Send Email

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 Statistics

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
}

WebSocket API

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

Connection

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);
};

Event Types

Server Status

Sent every 5 seconds with current status.

{
  "type": "status",
  "data": {
    "uptime": 3600,
    "memory": { ... },
    "modules": { ... }
  }
}

Configuration Updated

{
  "type": "configUpdated",
  "data": { ... }
}

Module Events

{
  "type": "moduleStarted",
  "data": {
    "module": "http",
    "status": "running"
  }
}

Virtual Host Events

{
  "type": "vhostCreated",
  "data": {
    "id": 1,
    "domain": "example.com"
  }
}
{
  "type": "vhostUpdated",
  "data": { ... }
}
{
  "type": "vhostDeleted",
  "data": {
    "id": 1
  }
}

DNS Events

{
  "type": "dnsZoneCreated",
  "data": {
    "name": "example.com"
  }
}
{
  "type": "dnsRecordAdded",
  "data": {
    "zone": "example.com",
    "record": { ... }
  }
}

Email Events

{
  "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
  }
}

Rate Limiting

Currently no rate limiting is implemented. For production:

  1. Implement rate limiting middleware
  2. Track requests per IP/user
  3. Return 429 Too Many Requests when exceeded
  4. Include Retry-After header

Error Codes

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

SDK Examples

JavaScript/Node.js

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'
);

Python

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

<?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'
);
?>

Best Practices

1. Authentication

  • Never hardcode credentials
  • Use environment variables
  • Rotate passwords regularly
  • Use HTTPS in production

2. Error Handling

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);
  }
}

3. Rate Limiting

  • Implement exponential backoff
  • Cache responses when appropriate
  • Use WebSocket for real-time data

4. Data Validation

  • Validate all inputs before sending
  • Check response status codes
  • Handle edge cases

5. Testing

// 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);

Troubleshooting

Connection Refused

  • Check if server is running
  • Verify port number (default 3000)
  • Check firewall settings

Authentication Failed

  • Verify username/password
  • Check Authorization header format
  • Ensure credentials are base64 encoded

Module Not Running

  • Check module status in admin panel
  • Start module via API or UI
  • Review server logs

API Returns 503

  • Module is not running
  • Start module first: POST /api/modules/email/start

Changelog

Version 1.0.0

  • Initial API release
  • Server management endpoints
  • Configuration management
  • Module control
  • Virtual host management
  • DNS zone management
  • Email management
  • WebSocket support

Support

For API support:

  • Review this documentation
  • Check server logs
  • Test with curl/Postman
  • Report issues with request/response details

License

OneStack REST API - Part of OneStack Server Copyright © 2025