Internal API

Connection & Auth

Before using the Workspace Internal 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 { OblienClient } from 'oblien';
import { Workspace } from 'oblien/workspace';

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

const access = await ws.apiAccess.enable('ws_a1b2c3d4');
console.log(access.token);   // Gateway JWT (eyJhbG...)
console.log(access.enabled); // true
POST https://api.oblien.com/workspace/ws_a1b2c3d4/internal-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/internal-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 ws.network.update('ws_a1b2c3d4', { public_access: true });
// The SDK manages tokens automatically after enabling
const files = await ws.files.list('ws_a1b2c3d4', { dirPath: '/app' });
const result = await ws.exec.run('ws_a1b2c3d4', { cmd: ['ls', '-la'] });
await ws.terminal.create('ws_a1b2c3d4', { 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
  • Long-lived - call workspaceToken to get a 30-day JWT, suitable for SDKs, MCP servers, and CI pipelines

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 ws.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 ws.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 ws.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 ws.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 / rotateToken / workspaceTokenrawToken
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/internal-api-accessGETServer status
/workspace/:id/internal-api-access/enablePOSTEnable server
/workspace/:id/internal-api-access/disablePOSTDisable server
/workspace/:id/internal-api-access/tokenPOSTRotate token
/workspace/:id/internal-api-access/token/rawGETRaw token + IP
/workspace/:id/internal-api-access/reconnectPOSTReconnect
/workspace/:id/internal-api-access/workspacePOST30-day token