Management API

Category: Development

Management API

The PowBot Desktop Management API is a RESTful API that allows you to programmatically manage PowBot Desktop instances, accounts, and proxy configurations. This API enables automation, monitoring, and integration with external tools and services.

Overview

The Management API provides endpoints for:

  • Instance Management: Create, launch, stop, and monitor game client instances
  • Account Management: Manage OAuth and Legacy accounts, including character selection
  • Proxy Management: Configure and manage proxy settings for instances and accounts
  • Real-time Monitoring: Stream instance events and logs using Server-Sent Events (SSE)

Base URL

The Management API runs locally with PowBot Desktop and is always available at:

  • Local Server: http://localhost:39344/api/v1

The API is only accessible when PowBot Desktop is running. It does not require authentication and is accessible from localhost only. The API is not hosted externally - it runs as part of the PowBot Desktop application.

API Specification

The complete OpenAPI 3.1 specification for the Management API is available at the Management API Reference. You can download the OpenAPI spec from that page and use it to generate client libraries for your preferred programming language using tools like:

This allows you to work with the API using type-safe, auto-generated clients in your language of choice.

Quick Start

Check API Health

curl http://localhost:39344/api/v1/health

Response:

{
  "status": "ok",
  "version": "1.0.0"
}

List All Instances

curl http://localhost:39344/api/v1/instances

Launch an Instance

Launch an instance with an existing account:

curl -X POST http://localhost:39344/api/v1/instances/launch \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "acc-550e8400-e29b-41d4-a716-446655440000",
    "character_id": "char-550e8400-e29b-41d4-a716-446655440000",
    "proxy_id": "proxy-123"
  }'

Instance Management

Launching Instances

The Management API provides three ways to launch instances:

1. Launch with Account ID

Use an existing account (OAuth or Legacy) that's already configured:

POST /instances/launch
{
  "account_id": "acc-...",
  "character_id": "char-...",  // Optional for OAuth accounts
  "proxy_id": "proxy-123"       // Optional
}

2. Launch with Legacy Account Credentials

Create or update a Legacy account and launch an instance in one request:

POST /instances/launch_legacy_account
{
  "username": "PlayerName",
  "password": "password123",
  "bank_pin": "1234",           // Optional
  "proxy_id": "proxy-123"       // Optional
}

3. Launch with Jagex Account (OAuth)

Create or update a Jagex account and launch an instance:

POST /instances/launch_jagex_account
{
  "session_id": "session-...",
  "display_name": "PlayerName",
  "character_id": "char-...",
  "refresh_token": "refresh_token_here",
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "bank_pin": "1234",           // Optional
  "proxy_id": "proxy-123"       // Optional
}

Monitoring Instances

Get Instance Details

GET /instances/{id}

Returns full instance information including logs and notes.

Stream Instance Events (SSE)

Monitor instance status changes, script updates, and other events in real-time:

const eventSource = new EventSource('http://localhost:39344/api/v1/instances/{id}/events');

eventSource.addEventListener('status_change', (event) => {
  const data = JSON.parse(event.data);
  console.log('Status changed:', data);
});

eventSource.addEventListener('script_update', (event) => {
  const data = JSON.parse(event.data);
  console.log('Script updated:', data);
});

Stream Instance Logs (SSE)

Tail instance logs in real-time:

const logSource = new EventSource('http://localhost:39344/api/v1/instances/{id}/logs/tail');

logSource.addEventListener('log', (event) => {
  const logEntry = JSON.parse(event.data);
  console.log(`[${logEntry.level}] ${logEntry.message}`);
});

Executing Lua Code

Execute Lua code directly in a running instance:

POST /instances/{id}/execute
{
  "code": "print('Hello from API!')"
}

Response:

{
  "session_id": "session-12345",
  "result": "Hello from API!",
  "error": null
}

Stopping Instances

POST /instances/{id}/stop

Account Management

List Accounts

GET /accounts

Returns all accounts (OAuth and Legacy) with their associated characters.

Create Account

OAuth Account

POST /accounts
{
  "account_type": "OAuth",
  "display_name": "PlayerName",
  "jagexAccount": {
    "email": "[email protected]",
    "oauth_tokens": {
      "access_token": "eyJhbGciOiJSUzI1NiIs...",
      "refresh_token": "refresh_token_here",
      "expires_in": 3600
    },
    "bank_pin": "1234"
  },
  "proxy_id": "proxy-123"
}

Legacy Account

POST /accounts
{
  "account_type": "Legacy",
  "display_name": "PlayerName",
  "legacyAccount": {
    "username": "PlayerName",
    "password": "password123",
    "bank_pin": "1234"
  },
  "proxy_id": "proxy-123"
}

Update Account

PUT /accounts/{id}
{
  "display_name": "Updated Name",
  "email": "[email protected]",
  "proxy_id": "proxy-456",
  "bank_pin": "5678"
}

Proxy Management

List Proxies

GET /proxies

Create Proxy

POST /proxies
{
  "name": "US East Proxy",
  "enabled": true,
  "host": "proxy.example.com",
  "port": 1080,
  "username": "proxyuser"  // Optional
}

Update Proxy

PUT /proxies/{id}
{
  "name": "Updated Proxy Name",
  "enabled": false,
  "host": "newproxy.example.com",
  "port": 8080
}

Common Use Cases

Automated Instance Management

import requests
import time

API_BASE = "http://localhost:39344/api/v1"

# Launch instance
response = requests.post(f"{API_BASE}/instances/launch", json={
    "account_id": "acc-...",
    "character_id": "char-...",
    "proxy_id": "proxy-123"
})
instance = response.json()

instance_id = instance["id"]

# Monitor instance status
event_source = requests.get(
    f"{API_BASE}/instances/{instance_id}/events",
    stream=True
)

for line in event_source.iter_lines():
    if line:
        event = json.loads(line.decode('utf-8'))
        if event["type"] == "status_change":
            print(f"Status: {event['data']['status']}")

Batch Instance Launch

accounts = [
    {"account_id": "acc-1", "character_id": "char-1"},
    {"account_id": "acc-2", "character_id": "char-2"},
    {"account_id": "acc-3", "character_id": "char-3"},
]

instances = []
for account in accounts:
    response = requests.post(
        f"{API_BASE}/instances/launch",
        json=account
    )
    instances.append(response.json())
    time.sleep(2)  # Stagger launches

print(f"Launched {len(instances)} instances")

Monitoring Multiple Instances

import asyncio
import aiohttp

async def monitor_instance(session, instance_id):
    async with session.get(
        f"{API_BASE}/instances/{instance_id}/events",
        headers={"Accept": "text/event-stream"}
    ) as response:
        async for line in response.content:
            if line.startswith(b"data: "):
                event = json.loads(line[6:].decode())
                print(f"Instance {instance_id}: {event}")

async def main():
    instances = ["instance-1", "instance-2", "instance-3"]
    async with aiohttp.ClientSession() as session:
        tasks = [
            monitor_instance(session, instance_id)
            for instance_id in instances
        ]
        await asyncio.gather(*tasks)

Error Handling

All endpoints return standard HTTP status codes:

  • 200 - Success
  • 201 - Created
  • 204 - No Content (successful deletion)
  • 400 - Bad Request (invalid parameters)
  • 404 - Not Found
  • 409 - Conflict (resource already exists or in use)
  • 408 - Request Timeout (Lua execution timeout)
  • 500 - Internal Server Error

Error responses follow this format:

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

Best Practices

  1. Use SSE for Real-time Monitoring: Instead of polling, use Server-Sent Events for monitoring instance status and logs
  2. Handle Errors Gracefully: Always check HTTP status codes and handle errors appropriately
  3. Stagger Instance Launches: When launching multiple instances, add delays between requests to avoid overwhelming the system
  4. Monitor Instance Health: Regularly check instance status and handle stopped/error states
  5. Use Account IDs: Prefer using existing account IDs over passing credentials directly when possible
  6. Clean Up Resources: Stop instances when done to free up system resources

Complete API Reference

For complete API documentation with all endpoints, request/response schemas, and examples, see the Management API Reference. You can download the OpenAPI specification from that page to generate client libraries for your preferred programming language.

Examples

JavaScript/TypeScript

const API_BASE = 'http://localhost:39344/api/v1';

async function launchInstance(accountId: string, characterId: string) {
  const response = await fetch(`${API_BASE}/instances/launch`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      account_id: accountId,
      character_id: characterId,
    }),
  });
  
  if (!response.ok) {
    throw new Error(`Failed to launch instance: ${response.statusText}`);
  }
  
  return await response.json();
}

// Monitor instance events
function monitorInstance(instanceId: string) {
  const eventSource = new EventSource(
    `${API_BASE}/instances/${instanceId}/events`
  );
  
  eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('Event:', data);
  };
  
  return eventSource;
}

Python

import requests
from typing import Optional, Dict, Any

class PowBotAPI:
    def __init__(self, base_url: str = "http://localhost:39344/api/v1"):
        self.base_url = base_url
    
    def launch_instance(
        self,
        account_id: Optional[str] = None,
        character_id: Optional[str] = None,
        proxy_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """Launch a new instance."""
        response = requests.post(
            f"{self.base_url}/instances/launch",
            json={
                "account_id": account_id,
                "character_id": character_id,
                "proxy_id": proxy_id,
            }
        )
        response.raise_for_status()
        return response.json()
    
    def get_instance(self, instance_id: str) -> Dict[str, Any]:
        """Get instance details."""
        response = requests.get(f"{self.base_url}/instances/{instance_id}")
        response.raise_for_status()
        return response.json()
    
    def stop_instance(self, instance_id: str) -> Dict[str, Any]:
        """Stop an instance."""
        response = requests.post(
            f"{self.base_url}/instances/{instance_id}/stop"
        )
        response.raise_for_status()
        return response.json()
    
    def list_instances(self) -> list:
        """List all instances."""
        response = requests.get(f"{self.base_url}/instances")
        response.raise_for_status()
        return response.json()

# Usage
api = PowBotAPI()
instance = api.launch_instance(
    account_id="acc-...",
    character_id="char-..."
)
print(f"Launched instance: {instance['id']}")

Next Steps