API Reference

Edge Tunnel

Expose a local port to the internet through the Oblien edge. Traffic to slug.domain is forwarded through a multiplexed WebSocket tunnel to an agent running on your machine.

How it works

  1. Create a tunnel specifying a name, port, and optional slug/domain
  2. Issue a token — a short-lived JWT for the tunnel connection
  3. Connect an agent (SDK or CLI) using the token — traffic flows through the WebSocket tunnel to localhost:port

The edge handles TLS termination. The agent authenticates with a JWT and maintains a persistent WebSocket connection to the broker.

Tunnels are independent of workspaces. They route traffic from the edge directly to a local port on whatever machine runs the agent.

SDK Usage

One-liner: create + connect

import Oblien from 'oblien';

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

const tunnel = await client.edgeTunnel.connect({
  name: 'dev-server',
  port: 3000,
});

console.log(tunnel.url);
// → https://dev-server-x7k.preview.oblien.com

tunnel.on('request', (streamId, port) => {
  console.log(`→ localhost:${port}`);
});

// Later…
tunnel.close();

Two-sided: SaaS backend generates token, client connects

// ── Server side (your SaaS backend) ──
import Oblien from 'oblien';

const admin = new Oblien({ clientId, clientSecret });

// Create a tunnel for each user/project
const { tunnel } = await admin.edgeTunnel.create({
  name: 'user-preview',
  port: 3000,
  slug: 'user-123-preview',
});

// Issue a token to hand to the client
const { token, connect_url } = await admin.edgeTunnel.issueToken(tunnel.id);

// Send token + connect_url to user's machine via your own API
// ── Client side (user's machine) ──
import { TunnelClient } from 'oblien';

const tc = new TunnelClient({
  connectUrl: connect_url,   // from your backend
  token: token,              // from your backend
  localPort: 3000,
});

tc.on('open', () => console.log('connected'));
tc.on('request', (id, port) => console.log(`→ localhost:${port}`));
tc.connect();

List tunnels

GET /edge/tunnels
curl "https://api.oblien.com/edge/tunnels" \
  -H "Authorization: Bearer $TOKEN"

Response

{
  "success": true,
  "tunnels": [
    {
      "id": 1,
      "name": "dev-server",
      "slug": "dev-server-x7k",
      "domain": "preview.oblien.com",
      "tunnel_id": "a1b2c3d4e5f6...",
      "port": 3000,
      "url": "https://dev-server-x7k.preview.oblien.com",
      "status": "active",
      "created_at": "2026-04-13T10:00:00Z"
    }
  ]
}

Create a tunnel

POST /edge/tunnels
Content-Type: application/json

{
  "name": "dev-server",
  "port": 3000,
  "slug": "my-app"
}
curl -X POST "https://api.oblien.com/edge/tunnels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"dev-server","port":3000}'

Parameters

ParameterTypeRequiredDescription
namestringYesDisplay name (max 100 chars)
portnumberYesTarget port on the agent machine (1–65535)
slugstringNoSubdomain slug (auto-generated if omitted)
domainstringNoBase domain (defaults to your edge domain)

Response

{
  "success": true,
  "tunnel": {
    "id": 1,
    "name": "dev-server",
    "slug": "dev-server-x7k",
    "domain": "preview.oblien.com",
    "tunnel_id": "a1b2c3d4e5f6...",
    "port": 3000,
    "url": "https://dev-server-x7k.preview.oblien.com",
    "status": "active"
  }
}

Update a tunnel

Update name, slug, or port.

PUT /edge/tunnels/:id
Content-Type: application/json

{ "name": "new-name", "port": 8080 }
ParameterTypeDescription
namestringNew display name
slugstringNew subdomain slug
portnumberNew target port

Issue a connection token

Generate a short-lived JWT for agent authentication. The token is valid for 24 hours.

POST /edge/tunnels/:id/token
curl -X POST "https://api.oblien.com/edge/tunnels/1/token" \
  -H "Authorization: Bearer $TOKEN"

Response

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "tunnel_id": "a1b2c3d4e5f6...",
  "port": 3000,
  "expires_in": "24h",
  "connect_url": "wss://edge.oblien.com/connect?token=eyJ..."
}

Enable / Disable

Toggle a tunnel without deleting it. Disabling removes the edge route (traffic stops), enabling re-creates it.

POST /edge/tunnels/:id/enable
POST /edge/tunnels/:id/disable

Delete a tunnel

Removes the edge route and DB record permanently.

DELETE /edge/tunnels/:id