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.
/api/v1/brands/{id}/domainsLists 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:readscope - 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
GET /api/v1/brands/brd_01m4tx5nj8emwbyf7y9vcf47x4/domains
Authorization: Bearer or_test_…
Response (200):
{
"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
GET /api/v1/brands/brd_01m4tx5nj8emwbyf7y9vcf47x4/domains
Authorization: Bearer or_test_…
Response (200):
{
"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 | 400 | The brand ID is malformed. | Fix the fields listed in details.issues and send the request again. |
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 | 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: api_version_unsupported, authentication_required, api_key_invalid, dry_run_not_supported, rate_limited, internal_error.