# List a brand's custom domains

> The brands.domains.list operation: GET /api/v1/brands/{id}/domains in the REST API and the brands_domains_list tool in the MCP server.

Lists the brand's custom domains (at most one for checkout and one for the customer portal) with their status and
the DNS records to create, and how many custom domains the organization uses against its plan's limit
(`custom_domains.max`, counted across all brands).

A `pending` domain doesn't serve anything yet; links keep using Ownrecord's own address until it is `verified`.
The records shown here are the general ones; `brands.domains.verify` asks the domain provider again and returns
the records it recommends for this domain, including a TXT record when it needs proof of ownership.

## At a glance

- **REST:** `GET /api/v1/brands/{id}/domains`
- **MCP tool:** `brands_domains_list`
- **Operation ID:** `brands.domains.list`
- **Scope:** Organization, or one of its legal entities or brands
- **Permission:** `brands:read`
- **Risk tier:** `read`
- **Dry run:** Not supported
- **Idempotency:** Not needed (read only)
- **Modes:** Test and live
- **Authentication:** API key with the `brands:read` scope
- **Since:** M9

## Request

### Path parameters

| Field | Type       | Description |
| ----- | ---------- | ----------- |
| `id`  | `brd_…` ID |             |

### Query parameters

This operation takes no query parameters.

## Response

`200 OK` with a JSON object:

| Field                         | Type                               | Description                                                                                                                                                    |
| ----------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `object`                      | `"list"`                           |                                                                                                                                                                |
| `data`                        | array of object                    |                                                                                                                                                                |
| `data[].object`               | `"brand_domain"`                   |                                                                                                                                                                |
| `data[].host`                 | string                             | The host name, lower case (internationalised names in their xn-- form).                                                                                        |
| `data[].purpose`              | one of `checkout`, `portal`        | `checkout` serves hosted checkout, `portal` the customer portal.                                                                                               |
| `data[].brandId`              | string                             |                                                                                                                                                                |
| `data[].status`               | one of `pending`, `verified`       | `verified` once the host points at Ownrecord and the challenge TXT record proves it's yours; `pending` until then.                                             |
| `data[].verifiedAt`           | date-time or null                  |                                                                                                                                                                |
| `data[].url`                  | string                             | The domain's base URL; hosted pages are served under it once it's verified.                                                                                    |
| `data[].dnsRecords`           | array of object                    | The DNS records to create at the domain's DNS provider: routing, Ownrecord's challenge TXT record, and the hosting provider's TXT record when it asks for one. |
| `data[].dnsRecords[].type`    | one of `A`, `AAAA`, `CNAME`, `TXT` |                                                                                                                                                                |
| `data[].dnsRecords[].name`    | string                             |                                                                                                                                                                |
| `data[].dnsRecords[].label`   | string                             |                                                                                                                                                                |
| `data[].dnsRecords[].value`   | string                             |                                                                                                                                                                |
| `data[].dnsRecords[].purpose` | one of `routing`, `ownership`      |                                                                                                                                                                |
| `data[].check`                | object or null                     |                                                                                                                                                                |
| `usage`                       | object                             | The organization's custom domains against its plan limit.                                                                                                      |
| `usage.used`                  | integer (at least 0)               | Custom domains of every brand of the organization.                                                                                                             |
| `usage.limit`                 | integer (at least 0)               | The plan's `custom_domains.max`.                                                                                                                               |

## Examples

### A verified checkout domain

```http
GET /api/v1/brands/brd_01m4tx5nj8emwbyf7y9vcf47x4/domains
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "list",
  "data": [
    {
      "object": "brand_domain",
      "host": "pay.acme-app.com",
      "purpose": "checkout",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "status": "verified",
      "verifiedAt": "2026-10-20T09:40:00.000Z",
      "url": "https://pay.acme-app.com",
      "dnsRecords": [
        {
          "type": "CNAME",
          "name": "pay.acme-app.com",
          "label": "pay",
          "value": "cname.vercel-dns.com",
          "purpose": "routing"
        },
        {
          "type": "TXT",
          "name": "_ownrecord-challenge.pay.acme-app.com",
          "label": "_ownrecord-challenge.pay",
          "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
          "purpose": "ownership"
        }
      ],
      "check": null
    }
  ],
  "usage": {
    "used": 1,
    "limit": 2
  }
}
```

### A checkout domain waiting for its DNS record

```http
GET /api/v1/brands/brd_01m4tx5nj8emwbyf7y9vcf47x4/domains
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "list",
  "data": [
    {
      "object": "brand_domain",
      "host": "pay.acme-app.com",
      "purpose": "checkout",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "status": "pending",
      "verifiedAt": null,
      "url": "https://pay.acme-app.com",
      "dnsRecords": [
        {
          "type": "CNAME",
          "name": "pay.acme-app.com",
          "label": "pay",
          "value": "cname.vercel-dns.com",
          "purpose": "routing"
        },
        {
          "type": "TXT",
          "name": "_ownrecord-challenge.pay.acme-app.com",
          "label": "_ownrecord-challenge.pay",
          "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
          "purpose": "ownership"
        }
      ],
      "check": null
    }
  ],
  "usage": {
    "used": 1,
    "limit": 2
  }
}
```

## Errors

| Code                                                                                     | HTTP status | When                                             | What to do                                                                                           |
| ---------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed)   | 400         | The brand ID is malformed.                       | Fix the fields listed in `details.issues` and send the request again.                                |
| [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found) | 404         | No brand with this ID is visible to the request. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied)   | 403         | You can't see this brand's settings.             | Ask an organization owner or admin for a role or scope that allows this action.                      |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`dry_run_not_supported`](https://ownrecord.io/docs/reference/errors.md#dry_run_not_supported), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
