Runtime API

Connection & Auth

Before using the Workspace Runtime API, the HTTP server inside the VM must be enabled. Once enabled, there are two ways to connect:

MethodURLAuthNetwork requirementUse case
Gatewayworkspace.oblien.comAuthorization: Bearer <gateway_jwt>public_access: trueExternal access - your app, SDK, CI, MCP
Direct10.x.x.x:9990Authorization: Bearer <raw_token>Private link from callerWorkspace-to-workspace over private network

Both methods hit the same server and the same endpoints. The difference is how you authenticate and how the request reaches the VM.


Enable the server

Start the internal server via the Oblien API. This returns a Gateway JWT for immediate use.

import Oblien from 'oblien';

const client = new Oblien({
  clientId: process.env.OBLIEN_CLIENT_ID!,
  clientSecret: process.env.OBLIEN_CLIENT_SECRET!,
});

const access = await client.workspaces.apiAccess.enable('ws_a1b2c3d4');
console.log(access.token);   // Gateway JWT (eyJhbG...)
console.log(access.enabled); // true
POST https://api.oblien.com/workspace/ws_a1b2c3d4/runtime-api-access/enable
X-Client-ID: your_client_id
X-Client-Secret: your_client_secret
curl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/runtime-api-access/enable" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"

Enable is idempotent - calling it on an already-enabled workspace returns a fresh JWT without restarting the server.


Gateway connection

Use the Gateway JWT to access the workspace through workspace.oblien.com. The JWT embeds the VM's private IP and port - the gateway decodes it and routes your request to the correct VM automatically.

The target workspace must have public_access: true in its network configuration. Without it, the gateway cannot reach the VM through the firewall. Enable it via the Network API:

await client.workspaces.network.update('ws_a1b2c3d4', { public_access: true });
// The SDK manages tokens automatically via client.workspaces.runtime()
const rt = await client.workspaces.runtime('ws_a1b2c3d4');

const files = await rt.files.list({ dirPath: '/app' });
const result = await rt.exec.run(['ls', '-la']);
await rt.terminal.create({ shell: '/bin/bash' });
GET https://workspace.oblien.com/files?path=/app
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# HTTP
curl "https://workspace.oblien.com/files?path=/app" \
  -H "Authorization: Bearer $GATEWAY_JWT"

# WebSocket
wscat -c "wss://workspace.oblien.com/ws" \
  -H "Authorization: Bearer $GATEWAY_JWT"

The URL is workspace.oblien.com/endpoint - not workspace.oblien.com/ws_id/endpoint. Routing is handled by the JWT payload, not the URL path.

Token lifetime

The standard Gateway JWT expires after ~1 hour. You have two options to manage this:

  • Rotate - call rotateToken or re-enable to get a fresh short-lived JWT
  • Force refresh - use client.workspaces.runtime(id, { force: true }) in the SDK to bypass the cached token

Both token types work the same way - Authorization: Bearer <token> against workspace.oblien.com. The only difference is expiry.


Direct connection

For workspace-to-workspace communication, connect directly to the target VM's private IP. This bypasses the gateway entirely - lower latency, no JWT overhead.

Setup flow

1. Enable the server on the target workspace
2. Create a private link from caller → target
3. Get the raw token + private IP of the target
4. Call the target directly from the calling workspace

Step 1: Enable the target

await client.workspaces.apiAccess.enable('ws_target');

Private links open a network path between two workspaces. Without a link, VMs cannot reach each other - they are network-dark by default. The link whitelists the caller's IP in the target workspace's firewall.

await client.workspaces.network.update('ws_target', {
  private_link_ids: ['ws_caller'],
});

The private_link_ids field takes workspace IDs, not IPs. The platform resolves each ID to its internal IP and configures the target's firewall automatically. See Private Links for details.

Step 3: Get the raw connection token

The raw token is a hex string used directly by the VM's auth middleware. Unlike the Gateway JWT, it doesn't embed routing info - you provide the IP yourself.

const raw = await client.workspaces.apiAccess.rawToken('ws_target');

console.log(raw.token); // "a1b2c3d4e5f6..."
console.log(raw.ip);    // "10.0.1.42"
console.log(raw.port);  // 9990

See the full endpoint reference at Raw token.

Step 4: Call from the other workspace

From code running inside ws_caller, call ws_target directly over the private network:

// Running inside ws_caller
const res = await fetch('http://10.0.1.42:9990/files?path=/app', {
  headers: { 'Authorization': `Bearer ${raw.token}` },
});
const files = await res.json();
curl "http://10.0.1.42:9990/exec" \
  -H "Authorization: Bearer a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{"cmd":["npm","test"]}'

Direct calls go VM-to-VM - no gateway, no JWT encoding/decoding overhead. This is the lowest-latency way to interact with a workspace.


Disable the server

Stop the internal server, kill all sessions, and close connections.

await client.workspaces.apiAccess.disable('ws_a1b2c3d4');

See the full endpoint reference at Disable server.


Token comparison

Gateway JWTRaw Connection Token
Use withworkspace.oblien.comDirect 10.x.x.x:9990
Auth headerAuthorization: Bearer <jwt>Authorization: Bearer <raw_token>
Lifetime~1 hour (standard) or 30 days (workspace token)Until rotated
Contains VM IPYes (embedded in JWT)No (you get the IP separately)
How to getenable / rotateTokenrawToken
When to useExternal access - apps, SDK, CI, MCPWorkspace-to-workspace orchestration

Full API access reference

All server management endpoints are on the Oblien API at api.oblien.com:

EndpointMethodDescription
/workspace/:id/runtime-api-accessGETServer status
/workspace/:id/runtime-api-access/enablePOSTEnable server
/workspace/:id/runtime-api-access/disablePOSTDisable server
/workspace/:id/runtime-api-access/tokenPOSTRotate token
/workspace/:id/runtime-api-access/token/rawGETRaw token + IP
/workspace/:id/runtime-api-access/reconnectPOSTReconnect
/workspace/:id/runtime-api-access/workspacePOST30-day token