API Reference

Domains

Connect a custom domain to a workspace with managed SSL. Routes are registered immediately; SSL becomes active once the domain resolves to an approved edge target. For an overview of all domain options, see the Domains guide.

Get domain

Get the current custom domain configuration for a workspace.

const domain = await ws.domains.get('ws_a1b2c3d4');

console.log(domain);
// {
//   customDomain: "app.example.com",
//   port: 3000,
//   sslStatus: "pending",
//   sslExpiry: null,
//   sslError: "DNS is not pointed to edge yet",
//   includeWww: false
// }
GET /workspace/:workspaceId/domain
curl "https://api.oblien.com/workspace/ws_a1b2c3d4/domain" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"

Response

{
  "success": true,
  "domain": {
    "customDomain": "app.example.com",
    "port": 3000,
    "sslStatus": "pending",
    "sslExpiry": null,
    "sslError": "DNS is not pointed to edge yet",
    "includeWww": false
  }
}

Returns "domain": null if no custom domain is connected.


Check DNS

Verify DNS records are correctly configured before connecting. This is a dry-run — no changes are made.

const check = await ws.domains.checkDNS('ws_a1b2c3d4', {
  domain: 'app.example.com',
});

if (check.verified) {
  console.log('DNS is ready — CNAME and ownership verified');
} else {
  console.log('Issues:', check.errors);
}
POST /workspace/:workspaceId/domain/check
{
  "domain": "app.example.com"
}
curl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/domain/check" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "app.example.com" }'

Parameters

ParameterTypeRequiredDescription
domainstringYesThe domain to verify

Response

{
  "success": true,
  "domain": "app.example.com",
  "enterprise": false,
  "verified": true,
  "cname": true,
  "ownership": true,
  "records": {
    "CNAME": ["edge.oblien.com"],
    "TXT": ["verify=ws_a1b2c3d4"]
  },
  "errors": [],
  "required_records": {
    "cname": { "host": "app.example.com", "target": "edge.oblien.com" },
    "txt": { "host": "_oblien.app.example.com", "value": "verify=ws_a1b2c3d4" }
  },
  "edge_ips": ["65.109.38.240"]
}

DNS records required

Before connecting, add these DNS records at your domain provider:

TypeNameValuePurpose
CNAMEapp (or @ for root)edge.oblien.comRoute traffic to Oblien edge
TXT_oblien.app.example.comverify=ws_a1b2c3d4Prove domain ownership

If using Cloudflare with proxy enabled (orange cloud), set an A record pointing to 65.109.38.240 instead of a CNAME. The TXT ownership record is still required.

Enterprise custom-domain grants can connect with edge DNS only. Those accounts may also use a branded TXT prefix such as _opsh instead of _oblien.


Connect domain

Connect a custom domain to a workspace. Oblien verifies ownership rules, registers the route immediately, and requests SSL if the domain is already pointed at an approved edge target.

const result = await ws.domains.connect('ws_a1b2c3d4', {
  domain: 'app.example.com',
  port: 3000,
  include_www: false,
});

console.log(result.url);
// "https://app.example.com"
POST /workspace/:workspaceId/domain
{
  "domain": "app.example.com",
  "port": 3000,
  "include_www": false
}
curl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/domain" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "app.example.com", "port": 3000 }'

Parameters

ParameterTypeRequiredDefaultDescription
domainstringYesDomain to connect (e.g. example.com, app.example.com)
portnumberNo3000Workspace port to route traffic to (1–65535)
include_wwwbooleanNofalseAlso redirect www. to the domain

Response

{
  "success": true,
  "domain": "app.example.com",
  "port": 3000,
  "ssl": {
    "status": "pending",
    "expiresAt": null,
    "error": "A/AAAA resolves to 104.21.1.12, 172.67.2.34 — not a known edge IP. Either CNAME to edge.oblien.com or point A record to one of: 65.109.38.240"
  },
  "dns": {
    "verified": false,
    "cname": false,
    "ownership": true,
    "errors": [
      "A/AAAA resolves to 104.21.1.12, 172.67.2.34 — not a known edge IP. Either CNAME to edge.oblien.com or point A record to one of: 65.109.38.240"
    ]
  },
  "url": "https://app.example.com"
}

What happens

  1. DNS verification — checks ownership requirements and current edge DNS signal
  2. Route registration — writes the domain→workspace mapping to etcd immediately
  3. SSL request — reuses or requests a certificate when the domain already resolves to an approved edge target
  4. Config storage — saves domain config, including ssl.status, ssl.expiresAt, and optional ssl.error

If ownership is valid but edge DNS is not ready yet, the connect request can still succeed with ssl.status: "pending". Run renew SSL later or wait for propagation.

Errors

CodeStatusCause
invalid_domain400Domain format is invalid
invalid_port400Port out of range (1–65535)
domain_in_use409Domain is connected to another workspace
dns_not_configured400Standard plans: TXT ownership missing or wrong. Enterprise: no valid edge DNS signal yet
ssl_failed500SSL certificate provisioning failed
vm_not_running409Workspace VM has no IP (not running)

Disconnect domain

Remove a custom domain from a workspace. Deletes the routing rule and clears the active SSL material from the edge.

await ws.domains.disconnect('ws_a1b2c3d4');
DELETE /workspace/:workspaceId/domain
curl -X DELETE "https://api.oblien.com/workspace/ws_a1b2c3d4/domain" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"

Response

{
  "success": true,
  "removed": "app.example.com"
}

Renew SSL

Force SSL certificate renewal for the connected domain. Certificates auto-renew, but you can trigger a manual renewal if needed.

const result = await ws.domains.renewSSL('ws_a1b2c3d4');

console.log(result.ssl.expiresAt);
// "2026-09-08"
POST /workspace/:workspaceId/domain/ssl/renew
curl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/domain/ssl/renew" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"

Response

{
  "success": true,
  "domain": "app.example.com",
  "ssl": {
    "status": "active",
    "expiresAt": "2026-09-08"
  }
}

Errors

CodeStatusCause
no_domain404No custom domain connected to this workspace
ssl_failed500ACME certificate renewal failed

Endpoint summary

EndpointMethodDescription
/workspace/:id/domainGETGet current domain config
/workspace/:id/domainPOSTConnect a custom domain
/workspace/:id/domainDELETEDisconnect custom domain
/workspace/:id/domain/checkPOSTVerify DNS configuration
/workspace/:id/domain/ssl/renewPOSTRenew SSL certificate
/domain/check-slugPOSTCheck slug availability
/domain/verifyPOSTVerify custom domain DNS

Standalone endpoints

These endpoints are not scoped to a specific workspace — use them for pre-flight checks before connecting domains or claiming slugs.

Check slug availability

Check whether a slug is available on a wildcard domain. No DNS check is needed since these are platform-managed subdomains.

POST /domain/check-slug
{
  "slug": "my-app",
  "domain": "preview.oblien.com"
}
curl -X POST "https://api.oblien.com/domain/check-slug" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "slug": "my-app" }'

Parameters

ParameterTypeRequiredDefaultDescription
slugstringYesDesired slug (3-48 chars, lowercase alphanumeric + hyphens)
domainstringNopreview.oblien.comBase domain to check against

Response

{
  "success": true,
  "slug": "my-app",
  "domain": "preview.oblien.com",
  "hostname": "my-app.preview.oblien.com",
  "url": "https://my-app.preview.oblien.com",
  "available": true
}

Verify custom domain DNS

Pre-flight DNS check for custom domains. Verifies CNAME or A/AAAA resolution to the edge and, for standard plans, the TXT ownership record.

POST /domain/verify
{
  "domain": "app.example.com",
  "resource_id": "ws_a1b2c3d4"
}
curl -X POST "https://api.oblien.com/domain/verify" \
  -H "X-Client-ID: $OBLIEN_CLIENT_ID" \
  -H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "app.example.com", "resource_id": "ws_a1b2c3d4" }'

Parameters

ParameterTypeRequiredDefaultDescription
domainstringYesCustom domain to verify (e.g. app.example.com)
resource_idstringNoWorkspace ID or page slug for TXT ownership check

Response

{
  "success": true,
  "domain": "app.example.com",
  "enterprise": false,
  "verified": true,
  "cname": true,
  "ownership": true,
  "records": {
    "CNAME": ["edge.oblien.com"],
    "TXT": ["verify=ws_a1b2c3d4"]
  },
  "errors": [],
  "required_records": {
    "cname": { "host": "app.example.com", "target": "edge.oblien.com" },
    "txt": { "host": "_oblien.app.example.com", "value": "verify=ws_a1b2c3d4" }
  },
  "edge_ips": ["65.109.38.240"]
}

Enterprise users with custom domains see "enterprise": true — only edge DNS verification is required, and required_records won't include a TXT entry. The TXT host may also use a branded prefix instead of _oblien.