> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sailresearch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom domains

> Serve a Sailbox HTTP listener on your own domain with automatic TLS

Every HTTP listener gets a generated `https://...` URL on a Sail domain. With
a custom domain, the same listener also answers on a hostname you own, such
as `app.example.com`. Sail obtains and renews the TLS certificate for you.
There is nothing to upload and no certificate to manage.

## Add a custom domain

Adding a domain is a three step process.

### 1. Expose an HTTP listener

Expose the guest port as an HTTP listener, at creation time or later. See
[Networking](/sailboxes-networking) for details.

### 2. Point your domain at your target address

Every organization has its own target address under
`sailboxes.sailresearch.com`. Pointing your domain at it is what proves your
organization controls the domain, so no one else can register it. Find your
target with:

```bash theme={null}
curl "https://sailbox-api.sailresearch.com/v1/custom-domains" \
  -H "Authorization: Bearer $SAIL_API_KEY"
```

```json theme={null}
{
  "cname_target": "<your-target>.sailboxes.sailresearch.com"
}
```

Create a CNAME record at your DNS provider:

```
app.example.com  CNAME  <your-target>.sailboxes.sailresearch.com
```

For an apex domain like `example.com`, standard CNAME records are not
allowed at the zone root, and ALIAS-style records hide the target name. Use
your provider's ALIAS or ANAME record type for routing, and add a TXT record
that carries the proof instead:

```
example.com                 ALIAS  <your-target>.sailboxes.sailresearch.com
_sail-domains.example.com   TXT    <your-target>.sailboxes.sailresearch.com
```

Some DNS providers proxy or accelerate traffic for a record by default. Turn
that off for this record. The record must resolve directly to the Sail
target.

These records are your standing authorization: any record that names a
target keeps authorizing that organization. If you switch organizations or
stop using Sail, remove the old records.

### 3. Register the domain

Register the domain against the Sailbox and guest port. Sail checks that the
DNS record is in place, then starts serving the hostname:

```bash theme={null}
curl -X POST "https://sailbox-api.sailresearch.com/v1/sailboxes/$SAILBOX_ID/domains" \
  -H "Authorization: Bearer $SAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "app.example.com", "guest_port": 3000}'
```

```json theme={null}
{
  "domain": "app.example.com",
  "sailbox_id": "sb_...",
  "guest_port": 3000,
  "url": "https://app.example.com",
  "cname_target": "<your-target>.sailboxes.sailresearch.com",
  "created_at": "2026-07-28T12:00:00Z"
}
```

`guest_port` is required and must identify an exposed HTTP listener.

If the DNS record has not propagated yet, registration fails with
instructions. Wait for propagation and try again.

The TLS certificate is issued on the first HTTPS request to the domain. That
first request can take up to a minute while the certificate is obtained;
after that, requests are served immediately. Certificates renew
automatically for as long as the domain stays registered and the DNS record
stays in place.

Plain HTTP requests to the domain redirect to HTTPS.

## List and remove domains

The list response also includes your organization's `cname_target`.

```bash theme={null}
curl "https://sailbox-api.sailresearch.com/v1/sailboxes/$SAILBOX_ID/domains" \
  -H "Authorization: Bearer $SAIL_API_KEY"

curl -X DELETE "https://sailbox-api.sailresearch.com/v1/sailboxes/$SAILBOX_ID/domains/app.example.com" \
  -H "Authorization: Bearer $SAIL_API_KEY"
```

Removing a domain stops routing and certificate renewal for it. Removing the
listener the domain points at removes its domains too.

## Notes

* A domain can be registered to one Sailbox listener at a time.
* Wildcard domains such as `*.example.com` are not supported. Register each
  hostname individually.
* Custom domains apply to HTTP listeners. TCP listeners already work with
  any hostname you CNAME at their endpoint, because TCP connections are
  routed by port and passed through without TLS termination.
* Listener allowlists keep working behind a custom domain.
* The domain keeps working across sleep and resume. A request to a sleeping
  Sailbox wakes it, like on the generated URL. While a Sailbox is paused,
  its domains stay registered but requests fail until you resume it.
  Terminating the Sailbox stops its domains.
* On a private Sailbox, only its creator can add or remove domains.
