On this page

Custom domains let you expose MIOSA previews, computers, and deployments under tenant-owned FQDNs. There are four related surfaces:

  • Computer custom domains map one fully qualified domain, such as app.yourdomain.com, to one Computer service.
  • Deployment custom domains map one fully qualified domain, such as program.drsmithclinic.com, to one Deployment.
  • Tenant preview domains white-label generated preview links for the whole organization. After configuration, sandbox /expose responses use URLs such as https://5173-sbx01j9x.sandbox.cliniciq.dev.
  • Workspace and project preview domains override the organization preview domain for one client workspace or one project.

MIOSA handles verification and automatic TLS certificate issuance via Caddy on-demand TLS.

Nested base paths: /api/v1/computers/{id}/domains and /api/v1/deployments/{id}/domains.

Flat frontend-compatible base path: /api/v1/custom-domains.


Quick Start

import { Miosa } from '@miosa/sdk';

const client = new Miosa();

// 1. Register the domain
const domain = await client.domains.register(computerId, {
  domain: 'app.yourcompany.com',
});
console.log(domain.verificationTarget); // e.g. "verify.miosa.ai"

// 2. Add a CNAME record at your DNS provider:
//    app.yourcompany.com → verify.miosa.ai

// 3. Trigger verification
const verified = await client.domains.verify(computerId, domain.id);
console.log(verified.status); // "verified" or "failed"
# Register
curl -X POST https://api.miosa.ai/api/v1/computers/{id}/domains 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"domain": "app.yourcompany.com"}'

Endpoints

Computer custom domains

MethodPathDescription
POST/computers/{id}/domainsRegister a custom domain
GET/computers/{id}/domainsList domains for a computer
POST/computers/{id}/domains/{domain_id}/verifyTrigger DNS verification
DELETE/computers/{id}/domains/{domain_id}Remove a domain

Deployment custom domains

MethodPathDescription
POST/deployments/{id}/domainsRegister a custom domain
GET/deployments/{id}/domainsList domains for a deployment

Flat custom domains

MethodPathDescription
GET/custom-domains?computer_id={id}List domains for a computer
GET/custom-domains?deployment_id={id}List domains for a deployment
POST/custom-domainsRegister a domain with computer_id or deployment_id
DELETE/custom-domains/{id}Remove a domain

Tenant preview domains

MethodPathDescription
GET/tenant/preview-domainRead the tenant preview domain
PUT/tenant/preview-domainSet the tenant preview domain
DELETE/tenant/preview-domainClear the tenant preview domain
GET/tenant/preview-domain/verifyCheck DNS/TLS readiness

Workspace and project preview domains

MethodPathDescription
GET/workspaces/{id}/preview-domainRead the workspace preview domain
PUT/workspaces/{id}/preview-domainSet the workspace preview domain
DELETE/workspaces/{id}/preview-domainClear the workspace preview domain
GET/workspaces/{id}/preview-domain/verifyCheck workspace DNS readiness
GET/projects/{id}/preview-domainRead the project preview domain
PUT/projects/{id}/preview-domainSet the project preview domain
DELETE/projects/{id}/preview-domainClear the project preview domain
GET/projects/{id}/preview-domain/verifyCheck project DNS readiness

Use a tenant preview domain when generated app/artifact preview URLs should use your organization’s domain instead of the platform default miosa.app.

curl -X PUT https://api.miosa.ai/api/v1/tenant/preview-domain 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"preview_domain":"preview.yourcompany.com"}'

Then expose a sandbox port:

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/expose 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"port":5173}'

Response:

{
  "url": "https://5173-sbx01j9x.sandbox.preview.yourcompany.com"
}

For a client workspace domain:

curl -X PUT https://api.miosa.ai/api/v1/workspaces/$WORKSPACE_ID/preview-domain 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"preview_domain":"drsmithclinic.com"}'

For a single project domain:

curl -X PUT https://api.miosa.ai/api/v1/projects/$PROJECT_ID/preview-domain 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"preview_domain":"program.drsmithclinic.com"}'

DNS must delegate wildcard traffic to the MIOSA preview router:

Record typeNameValueUsed for
CNAME*proxy.miosa.aihttps://{slug}.{domain} managed deployment/computer/default preview URLs
CNAME*.sandboxproxy.miosa.aihttps://{port}-{slug}.sandbox.{domain} sandbox port previews

If no preview domain is configured, MIOSA returns the managed miosa.app fallback. This fallback remains available even after custom domains are attached.

Preview-domain precedence is project → workspace → tenant → MIOSA fallback. Exact deployment/computer custom domains still take priority over preview-domain inheritance.


Register a Domain

POST /api/v1/computers/{id}/domains

Request Body

FieldTypeRequiredDescription
domainstringYesFully qualified domain name. RFC 1123 hostname, max 253 chars

Response — 201 Created

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "computer_id": "...",
    "deployment_id": null,
    "tenant_id": "...",
    "workspace_id": "660e8400-e29b-41d4-a716-446655440001",
    "project_id": "770e8400-e29b-41d4-a716-446655440002",
    "fqdn": "app.yourcompany.com",
    "status": "pending",
    "verification_target": "verify.miosa.ai",
    "verified_at": null,
    "tls_issued_at": null,
    "external_workspace_id": "clinic_123",
    "external_user_id": "dr-smith-456",
    "external_project_id": "project_789",
    "created_at": "2026-04-11T00:00:00Z",
    "updated_at": "2026-04-11T00:00:00Z"
  }
}

Status Values

StatusDescription
pendingRegistered; awaiting DNS verification
verifiedCNAME confirmed; Caddy may issue a cert
activeTLS certificate issued and in use
failedVerification or TLS issuance failed
removedDomain detached (soft marker before deletion)

Errors

StatusErrorCause
409has already been takenFQDN already registered (globally unique)
422Validation errorInvalid FQDN format or ends with miosa.ai
curl -X POST https://api.miosa.ai/api/v1/computers/{id}/domains 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"domain": "preview.yourapp.io"}'

Register a deployment domain

curl -X POST https://api.miosa.ai/api/v1/deployments/{id}/domains 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"domain": "program.drsmithclinic.com"}'

Deployment domains inherit workspace_id, project_id, and external attribution from the deployment.


List Domains

GET /api/v1/computers/{id}/domains

Response — 200 OK

{
  "data": [
    {
      "id": "...",
      "fqdn": "app.yourcompany.com",
      "status": "active",
      "verified_at": "2026-04-11T01:00:00Z",
      "tls_issued_at": "2026-04-11T01:05:00Z",
      "created_at": "2026-04-11T00:00:00Z"
    }
  ],
  "total": 1
}
curl https://api.miosa.ai/api/v1/computers/{id}/domains 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Verify a Domain

POST /api/v1/computers/{id}/domains/{domain_id}/verify

Checks that the CNAME record at fqdn resolves to verification_target. On success the domain transitions to "verified" and Caddy will issue a TLS certificate on the next HTTPS request to the FQDN.

Path Parameters

ParameterTypeDescription
idUUIDComputer ID
domain_idUUIDDomain ID

Response — 200 OK

{
  "data": {
    "id": "...",
    "fqdn": "app.yourcompany.com",
    "status": "verified",
    "verified_at": "2026-04-11T01:00:00Z"
  }
}

Errors

StatusErrorCause
409domain is already verifiedAlready completed
422CNAME not foundDNS record missing or not yet propagated
curl -X POST https://api.miosa.ai/api/v1/computers/{id}/domains/{domain_id}/verify 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Remove a Domain

DELETE /api/v1/computers/{id}/domains/{domain_id}

Detaches the domain from the computer. The certificate is not revoked immediately (Caddy lets it expire naturally), but the domain will no longer route to the computer.

Response — 200 OK

{
  "data": { "id": "...", "fqdn": "app.yourcompany.com", "status": "removed" }
}
curl -X DELETE https://api.miosa.ai/api/v1/computers/{id}/domains/{domain_id} 
  -H "Authorization: Bearer $MIOSA_API_KEY"

DNS Setup Reference

After registering a domain, add the following DNS record at your registrar or DNS provider:

RecordHostValue
CNAMEapp (or full subdomain)verify.miosa.ai

DNS propagation typically takes 1–60 minutes. Call verify once propagation is complete. If verification fails, wait a few minutes and retry — the endpoint is idempotent.


Common Recipes

Automate full domain onboarding

import time
from miosa import Miosa

client = Miosa()

domain = client.domains.register(computer_id, fqdn="api.yourcompany.com")
print(f"Add CNAME: {domain.fqdn} → {domain.verification_target}")
print("Waiting for DNS propagation...")

while True:
    result = client.domains.verify(computer_id, domain.id)
    if result.status == "verified":
        print("Domain verified! TLS will be issued on first HTTPS request.")
        break
    elif result.status == "failed":
        raise RuntimeError("Verification failed — check your DNS records.")
    time.sleep(30)

List all pending domains (potential stuck ACME issuances)

const computers = await client.computers.list();
for (const computer of computers.data) {
  const { data: domains } = await client.domains.list(computer.id);
  const pending = domains.filter(d => d.status === 'pending');
  if (pending.length > 0) {
    console.log(`${computer.name}: ${pending.length} domain(s) pending verification`);
  }
}

Was this helpful?