---
title: "List a site's custom domains"
method: GET
path: "/api/v1/sites/{slug}/custom-domains"
tags: ["Domains"]
---

# List a site's custom domains

`GET /api/v1/sites/{slug}/custom-domains`

## Request

- Base URL: `https://api.dotsy.ai`
- URL: `https://api.dotsy.ai/api/v1/sites/{slug}/custom-domains`
- Auth: HTTP bearer

Every hostname connected to (or being connected to) the site, with its status and the DNS records still to create. Hostnames that are not connected yet carry a live DNS check on each record. Stale external hostnames are re-checked with Cloudflare in the background, so a poll sees fresher data next time. Needs the site owner. Editors, viewers, guest tokens (`guest_requires_account`) and keys scoped to other sites are refused.

## Path parameters

- `slug` string, required

## Response `200`

The site's domains.

- ListCustomDomainsResponse
  - `domains` CustomDomain[], required
    - `host` string, required
    - `slug` string, required: The site this hostname serves.
    - `kind` 'internal' | 'external', required: `internal`: a nested subdomain of the platform's own site domain, connected at once with no DNS. `external`: a domain you own, which needs DNS records and a certificate.
    - `status` 'pending_dns' | 'pending_cert' | 'connected' | 'error', required: `pending_dns`: waiting for the DNS records. `pending_cert`: DNS is right, the HTTPS certificate is being issued. `connected`: live. `error`: Cloudflare could not set the hostname up (see `lastError`); it no longer holds a hostname slot.
    - `isPrimary` boolean, required: The primary host is the canonical address: the site's other connected hosts redirect (301) to it.
    - `lastError` string, nullable, required: Why setup failed or stalled, or null.
    - `createdAt` number, required: When the hostname was added, Unix ms.
    - `verifiedAt` number, required: When the hostname was last verified, Unix ms.
    - `connectSessionId` string, nullable, required: The connect session (`cs_…`) this host belongs to, or null (internal hosts, expired sessions).
    - `lastCheckedAt` number, required: When Cloudflare was last asked about this hostname, Unix ms.
    - `dnsRecords` DnsRecord[], required: The records to create. Empty for internal hosts. For a connected host they are all `found`; otherwise each carries a live `recordStatus`.
      - `type` string, required: DNS record type, e.g. `CNAME`, `TXT` or `A`.
      - `name` string, required: The record name to enter at the DNS provider (relative to the zone, e.g. `www` or `_acme-challenge.www`).
      - `value` string, required: The record value to enter.
      - `purpose` 'routing' | 'dcv' | 'apex', required: `routing`: points the hostname at Dotsy. `apex`: the same for a bare domain. `dcv`: proves you control the domain so the certificate can be issued.
      - `host` string: On `connect` records only: the session host this row belongs to.
      - `recordStatus` 'found' | 'missing' | 'mismatch' | 'waiting' | 'duplicate': A live DNS check of this record. Absent when no check has run. `duplicate` means extra TXT records at this name are blocking the certificate.
      - `nameError` 'doubled_suffix': The name looks like it was pasted as a full hostname and the provider appended the zone to it.
      - `useInstead` string: With `nameError`: the relative name to enter instead.
      - `dnsTxtCount` number: With `recordStatus: duplicate`: how many TXT answers exist at this name.
      - `dcvExpectedValues` string[]: Every certificate-check token that is currently acceptable at this name (Cloudflare rotated while pending).

## Other responses

- `401`: Missing or invalid credentials.
- `403`: Not allowed: only the site owner manages domains, and guest tokens cannot.
- `404`: No such site (`site_not_found`).

---

[API](https://skmtc.dev/dotsy/apis/dotsy-api.md) · [All operations](https://skmtc.dev/dotsy/apis/dotsy-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dotsy/apis/dotsy-api/revisions/4272ed3b85d7?raw)
