---
title: "Custom Domains API Reference"
description: "Endpoints for managing custom domains in Linkbreakers. These endpoints allow you to register, verify, and manage custom domains for your workspace."
canonical: "https://linkbreakers.com/help/api/custom-domains"
---

# Custom Domains

Endpoints for managing custom domains in Linkbreakers. These endpoints allow you to register, verify, and manage custom domains for your workspace.

## Custom Domains

## [#](#custom-domains-object)The Custom Domain object

Captures a branded hostname that Linkbreakers provisions for a workspace so scans and shortlinks resolve under the customer's domain, including verification and certificate lifecycle state.

activatedAt

string (date-time)

Timestamp when the domain became active after passing verification and certificate checks.

certificateExpiresAt

string (date-time)

When the certificate currently serving this domain expires. While the status is STATUS\_RENEWAL\_PENDING the domain keeps working until this date, then stops.

cloudflareHostnameStatus

string

Raw hostname status reported by the certificate provider, recorded at the last check.

cloudflareSslStatus

string

Raw SSL status reported by the certificate provider, recorded at the last check.

createdAt

string (date-time)

Timestamp when the domain was created

id

string

Unique identifier for the custom domain (UUID)

lastCheckedAt

string (date-time)

Timestamp of the last verification check

lastError

string

Human-readable reason the domain is not fully active, as reported at the last check. Empty when the domain is healthy.

name

string

The domain name

rootDestination

string

URL where visitors are redirected when accessing your custom domain without a path (e.g., qr.yourdomain.com). This redirect is not tracked and serves purely for white-label purposes—preventing visitors from seeing linkbreakers.com branding. If not specified, redirects to linkbreakers.com by default.

status

string (enum)

The status of a custom domain of that certificate cannot be validated. It stops working at certificate\_expires\_at.

##### Allowed values

`STATUS_UNSPECIFIED`

The status is not specified

`STATUS_INACTIVE`

The domain is inactive. It was created but not checked yet.

`STATUS_DOMAIN_PENDING`

The domain is pending. Last time it was checked, it was not pointing to the correct Linkbreakers subdomain.

`STATUS_VERIFICATION_PENDING`

The domain is pending verification. Please verify through TXT record.

`STATUS_CERTIFICATE_PENDING`

The domain is pending certificate. The SSL certificate is not yet ready.

`STATUS_ACTIVE`

The domain is fully active

`STATUS_RENEWAL_PENDING`

The domain is still serving traffic on a valid certificate, but the renewal

`STATUS_EXPIRED`

The certificate expired or was withdrawn. The domain no longer serves HTTPS.

updatedAt

string (date-time)

Timestamp when the domain was last updated

workspaceId

string

The ID of the workspace this domain belongs to (UUID)

[Learn moreLearn more about branded links in Linkbreakers.](https://linkbreakers.com/help/article/how-to-create-branded-links-in-linkbreakers)

Example object

```json
{
  "activatedAt": "2026-10-25T05:41:08.898Z",
  "certificateExpiresAt": "2026-10-25T05:41:08.898Z",
  "cloudflareHostnameStatus": "active",
  "cloudflareSslStatus": "pending_validation",
  "createdAt": "2026-10-25T05:41:08.898Z",
  "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "lastCheckedAt": "2026-10-25T05:41:08.898Z",
  "lastError": "string",
  "name": "example.com",
  "rootDestination": "https://example.com",
  "status": "STATUS_ACTIVE",
  "updatedAt": "2026-10-25T05:41:08.898Z",
  "workspaceId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
}
```

GET

`/v1/custom-domains`

Requires auth

## [#](#list-custom-domains)List custom domains

Retrieves the custom domains for your workspace Requires the \`domains:read\` scope.

### [#](#list-custom-domains-parameters)Parameters

#### query parameters

status

string

query

Filter by the status of the custom domains to list. Optional. of that certificate cannot be validated. It stops working at certificate\_expires\_at.

##### Allowed values

`STATUS_UNSPECIFIED`

The status is not specified

`STATUS_INACTIVE`

The domain is inactive. It was created but not checked yet.

`STATUS_DOMAIN_PENDING`

The domain is pending. Last time it was checked, it was not pointing to the correct Linkbreakers subdomain.

`STATUS_VERIFICATION_PENDING`

The domain is pending verification. Please verify through TXT record.

`STATUS_CERTIFICATE_PENDING`

The domain is pending certificate. The SSL certificate is not yet ready.

`STATUS_ACTIVE`

The domain is fully active

`STATUS_RENEWAL_PENDING`

The domain is still serving traffic on a valid certificate, but the renewal

`STATUS_EXPIRED`

The certificate expired or was withdrawn. The domain no longer serves HTTPS.

pageSize

integer (int64)

query

Maximum number of custom domains to return. Defaults to 100, capped at 1000.

pageToken

string

query

Cursor from a previous response's next\_page\_token. Empty starts at the first page. Pages are ordered by (created\_at, id), which never change, so a record cannot move between pages while a client is walking them.

cursor

string

query

Opaque cursor from the previous page's nextPageToken. Same as pageToken; when both are sent, pageToken wins.

### [#](#list-custom-domains-response)Response

200

Everything worked as expected.

customDomains

array<object>

nextPageToken

string

Cursor to continue listing custom domains. Empty on the last page.

totalCount

integer (int64)

How many records exist in total, so a client can tell a complete answer from a page of one. A local-first client reads absence from this list as deletion, and may only do so when the count it was given matches what it received: without that, one page would look like the whole model and everything beyond it would be removed locally.

### [#](#list-custom-domains-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X GET "https://api.linkbreakers.com/v1/custom-domains?status={status}&pageSize={pageSize}&pageToken={pageToken}&cursor={cursor}" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

Typical response

```json
{
  "customDomains": [
    {
      "activatedAt": "2026-10-25T05:41:08.897Z",
      "certificateExpiresAt": "2026-10-25T05:41:08.897Z",
      "cloudflareHostnameStatus": "active",
      "cloudflareSslStatus": "pending_validation",
      "createdAt": "2026-10-25T05:41:08.897Z",
      "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
      "lastCheckedAt": "2026-10-25T05:41:08.897Z",
      "lastError": "string",
      "name": "example.com",
      "rootDestination": "https://example.com",
      "status": "STATUS_ACTIVE",
      "updatedAt": "2026-10-25T05:41:08.897Z",
      "workspaceId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
    }
  ],
  "nextPageToken": "string",
  "totalCount": 0
}
```

Base URL: `https://api.linkbreakers.com`

GET

`/v1/custom-domains/{id}`

Requires auth

## [#](#get-custom-domain-details)Get custom domain details

Retrieves information about a custom domain including its verification status and timestamps. Requires the \`domains:read\` scope.

### [#](#get-custom-domain-details-parameters)Parameters

#### path parameters

id

string

Required

path

The ID of the custom domain to retrieve (UUID)

### [#](#get-custom-domain-details-response)Response

200

Everything worked as expected.

customDomain

object

Captures a branded hostname that Linkbreakers provisions for a workspace so scans and shortlinks resolve under the customer's domain, including verification and certificate lifecycle state.

### [#](#get-custom-domain-details-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X GET "https://api.linkbreakers.com/v1/custom-domains/{id}" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

Typical response

```json
{
  "customDomain": {
    "activatedAt": "2026-10-25T05:41:08.898Z",
    "certificateExpiresAt": "2026-10-25T05:41:08.898Z",
    "cloudflareHostnameStatus": "active",
    "cloudflareSslStatus": "pending_validation",
    "createdAt": "2026-10-25T05:41:08.898Z",
    "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "lastCheckedAt": "2026-10-25T05:41:08.898Z",
    "lastError": "string",
    "name": "example.com",
    "rootDestination": "https://example.com",
    "status": "STATUS_ACTIVE",
    "updatedAt": "2026-10-25T05:41:08.898Z",
    "workspaceId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  }
}
```

Base URL: `https://api.linkbreakers.com`

GET

`/v1/custom-domains/{id}/setup-guide`

Requires auth

## [#](#get-the-setup-guide-for-a-custom-domain)Get the setup guide for a custom domain

Detects which DNS provider manages the domain from its nameservers and returns everything needed to connect it: the provider's name and a link to its DNS settings, the exact records to add (with the host written the way that provider expects it), provider-specific hints, and a one-click setup URL when the provider supports Domain Connect for Linkbreakers. Requires the \`domains:read\` scope.

### [#](#get-the-setup-guide-for-a-custom-domain-parameters)Parameters

#### path parameters

id

string

Required

path

The ID of the custom domain (UUID)

### [#](#get-the-setup-guide-for-a-custom-domain-response)Response

200

Everything worked as expected.

setupGuide

object

Everything needed to connect a custom domain, derived from the domain's DNS: who manages it, where to go, and what to add.

### [#](#get-the-setup-guide-for-a-custom-domain-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X GET "https://api.linkbreakers.com/v1/custom-domains/{id}/setup-guide" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

Typical response

```json
{
  "setupGuide": {
    "customDomainId": "links.example.com",
    "dnsProvider": "DNS_PROVIDER_UNSPECIFIED",
    "dnsProviderName": "string",
    "dnsSettingsUrl": "https://example.com",
    "domain": "links.example.com",
    "hints": [
      "CUSTOM_DOMAIN_SETUP_HINT_UNSPECIFIED"
    ],
    "host": "example.com",
    "hostFieldLabel": "string",
    "nameservers": [
      "string"
    ],
    "oneClickSetup": {
      "applyUrl": "https://example.com",
      "providerName": "string"
    },
    "records": [
      {
        "detected": false,
        "host": "example.com",
        "name": "string",
        "purpose": "DNS_RECORD_PURPOSE_UNSPECIFIED",
        "required": false,
        "type": "DNS_RECORD_TYPE_UNSPECIFIED",
        "value": "string"
      }
    ],
    "zone": "string"
  }
}
```

Base URL: `https://api.linkbreakers.com`

GET

`/v1/custom-domains/{id}/validation_instructions`

Requires auth

## [#](#get-the-validation-instructions)Get the validation instructions

Get the instructions for validating a custom domain. There may be a delay before the instructions are available. Requires the \`domains:read\` scope.

### [#](#get-the-validation-instructions-parameters)Parameters

#### path parameters

id

string

Required

path

The ID of the custom domain to retrieve (UUID)

### [#](#get-the-validation-instructions-response)Response

200

Everything worked as expected.

validations

array<object>

The list of validations that need to be performed

### [#](#get-the-validation-instructions-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X GET "https://api.linkbreakers.com/v1/custom-domains/{id}/validation_instructions" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

Typical response

```json
{
  "validations": [
    {
      "name": "string",
      "purpose": "PURPOSE_UNSPECIFIED",
      "type": "TYPE_UNSPECIFIED",
      "value": "string"
    }
  ]
}
```

Base URL: `https://api.linkbreakers.com`

POST

`/v1/custom-domains`

Requires auth

## [#](#create-a-custom-domain)Create a custom domain

This endpoint allows users to register a new custom domain that can be used with their Linkbreakers workspace. Requires the \`domains:write\` scope.

### [#](#create-a-custom-domain-parameters)Parameters

#### header parameters

Idempotency-Key

string

header

Makes retrying this request safe. See components.parameters.IdempotencyKey.

### [#](#create-a-custom-domain-request)Request body

name

string

The domain name to register. It must be a valid DNS and not already registered in Linkbreakers. Subdomains are also supported.

### [#](#create-a-custom-domain-response)Response

200

Everything worked as expected.

customDomain

object

Captures a branded hostname that Linkbreakers provisions for a workspace so scans and shortlinks resolve under the customer's domain, including verification and certificate lifecycle state.

### [#](#create-a-custom-domain-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X POST "https://api.linkbreakers.com/v1/custom-domains" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Idempotency-Key: string" \
  -H "Content-Type: application/json" \
  --data '{"name":"my-domain.com"}'
```

Sample payload (application/json)

```json
{
  "name": "my-domain.com"
}
```

Typical response

```json
{
  "customDomain": {
    "activatedAt": "2026-10-25T05:41:08.897Z",
    "certificateExpiresAt": "2026-10-25T05:41:08.897Z",
    "cloudflareHostnameStatus": "active",
    "cloudflareSslStatus": "pending_validation",
    "createdAt": "2026-10-25T05:41:08.897Z",
    "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "lastCheckedAt": "2026-10-25T05:41:08.897Z",
    "lastError": "string",
    "name": "example.com",
    "rootDestination": "https://example.com",
    "status": "STATUS_ACTIVE",
    "updatedAt": "2026-10-25T05:41:08.897Z",
    "workspaceId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  }
}
```

Base URL: `https://api.linkbreakers.com`

POST

`/v1/custom-domains/{id}/check`

Requires auth

## [#](#check-a-custom-domain)Check a custom domain

Check a custom domain by looking up its DNS records and TLS status. This is automatically done when the domain is created. It will update the domain status. Requires the \`domains:write\` scope.

### [#](#check-a-custom-domain-parameters)Parameters

#### path parameters

id

string

Required

path

The ID of the custom domain to retrieve (UUID)

#### header parameters

Idempotency-Key

string

header

Makes retrying this request safe. See components.parameters.IdempotencyKey.

### [#](#check-a-custom-domain-response)Response

200

Everything worked as expected.

customDomain

object

Captures a branded hostname that Linkbreakers provisions for a workspace so scans and shortlinks resolve under the customer's domain, including verification and certificate lifecycle state.

### [#](#check-a-custom-domain-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X POST "https://api.linkbreakers.com/v1/custom-domains/{id}/check" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Idempotency-Key: string"
```

Typical response

```json
{
  "customDomain": {
    "activatedAt": "2026-10-25T05:41:08.898Z",
    "certificateExpiresAt": "2026-10-25T05:41:08.898Z",
    "cloudflareHostnameStatus": "active",
    "cloudflareSslStatus": "pending_validation",
    "createdAt": "2026-10-25T05:41:08.898Z",
    "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "lastCheckedAt": "2026-10-25T05:41:08.898Z",
    "lastError": "string",
    "name": "example.com",
    "rootDestination": "https://example.com",
    "status": "STATUS_ACTIVE",
    "updatedAt": "2026-10-25T05:41:08.898Z",
    "workspaceId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  }
}
```

Base URL: `https://api.linkbreakers.com`

PATCH

`/v1/custom-domains/{id}`

Requires auth

## [#](#update-a-custom-domain)Update a custom domain

Update settings for a custom domain, such as the root destination URL. Requires the \`domains:write\` scope.

### [#](#update-a-custom-domain-parameters)Parameters

#### path parameters

id

string

Required

path

The ID of the custom domain to update (UUID)

#### header parameters

Idempotency-Key

string

header

Makes retrying this request safe. See components.parameters.IdempotencyKey.

### [#](#update-a-custom-domain-request)Request body

rootDestination

string

URL where visitors are redirected when accessing your custom domain without a path (e.g., qr.yourdomain.com). This redirect is not tracked and serves purely for white-label purposes—preventing visitors from seeing linkbreakers.com branding. Leave empty to redirect to linkbreakers.com by default.

### [#](#update-a-custom-domain-response)Response

200

Everything worked as expected.

customDomain

object

Captures a branded hostname that Linkbreakers provisions for a workspace so scans and shortlinks resolve under the customer's domain, including verification and certificate lifecycle state.

### [#](#update-a-custom-domain-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X PATCH "https://api.linkbreakers.com/v1/custom-domains/{id}" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Idempotency-Key: string" \
  -H "Content-Type: application/json" \
  --data '{"rootDestination":"https://example.com"}'
```

Sample payload (application/json)

```json
{
  "rootDestination": "https://example.com"
}
```

Typical response

```json
{
  "customDomain": {
    "activatedAt": "2026-10-25T05:41:08.898Z",
    "certificateExpiresAt": "2026-10-25T05:41:08.898Z",
    "cloudflareHostnameStatus": "active",
    "cloudflareSslStatus": "pending_validation",
    "createdAt": "2026-10-25T05:41:08.898Z",
    "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "lastCheckedAt": "2026-10-25T05:41:08.898Z",
    "lastError": "string",
    "name": "example.com",
    "rootDestination": "https://example.com",
    "status": "STATUS_ACTIVE",
    "updatedAt": "2026-10-25T05:41:08.898Z",
    "workspaceId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  }
}
```

Base URL: `https://api.linkbreakers.com`

DELETE

`/v1/custom-domains/{id}`

Requires auth

## [#](#delete-a-custom-domain)Delete a custom domain

Removes a custom domain from the workspace. This operation cannot be undone. Requires the \`domains:write\` scope.

### [#](#delete-a-custom-domain-parameters)Parameters

#### path parameters

id

string

Required

path

The ID of the custom domain to delete (UUID)

### [#](#delete-a-custom-domain-response)Response

200

Everything worked as expected.

No structured schema available for this section.

### [#](#delete-a-custom-domain-error)Error response

400-599

All endpoints may return an unexpected error payload when a request cannot be processed.

error

object

Required

Wrapped error response.

Example request (cURL)

```bash
curl -X DELETE "https://api.linkbreakers.com/v1/custom-domains/{id}" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

Typical response

```json
{}
```

Base URL: `https://api.linkbreakers.com`

---

Source: https://linkbreakers.com/help/api/custom-domains
