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

# Custom Domains

> White-label your signing experience by serving DocuTrust from your own domain with automatic SSL.

## Overview

Custom domains let you serve signing pages, emails, and API endpoints from your own branded domain (e.g., `sign.yourcompany.com`) instead of the default `spitshake.io`. DocuTrust handles DNS verification and automatic SSL certificate provisioning.

## Add a Custom Domain

Register a new domain with your account. The response includes DNS records you must create to verify ownership.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://spitshake.io/api/custom_domains" \
    -H "X-Auth-Token: YOUR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "domain": "sign.yourcompany.com"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "id": 42,
    "domain": "sign.yourcompany.com",
    "status": "pending",
    "primary": false,
    "verification_record_name": "_docutrust-verify.sign.yourcompany.com",
    "verification_record_value": "docutrust-verify=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "ssl_status": "pending",
    "dns_verified_at": null,
    "ssl_provisioned_at": null,
    "last_checked_at": null,
    "last_error": null,
    "created_at": "2026-04-08T15:00:00Z"
  }
  ```

  ```json 422 — Duplicate Domain theme={null}
  {
    "error": "The domain sign.yourcompany.com is already registered to this account."
  }
  ```

  ```json 422 — Invalid Domain theme={null}
  {
    "error": "Invalid domain format. Please provide a valid subdomain (e.g., sign.yourcompany.com)."
  }
  ```
</ResponseExample>

## DNS Setup

After adding a domain, create the following DNS records with your domain registrar:

### Required Records

| Type  | Name                                     | Value                                               | Purpose                     |
| ----- | ---------------------------------------- | --------------------------------------------------- | --------------------------- |
| CNAME | `sign.yourcompany.com`                   | `spitshake.io`                                      | Routes traffic to DocuTrust |
| TXT   | `_docutrust-verify.sign.yourcompany.com` | `docutrust-verify=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6` | Proves domain ownership     |

<Note>
  DNS propagation can take up to 48 hours, though most providers complete within 15 minutes. DocuTrust checks DNS records automatically every 10 minutes.
</Note>

## Status Lifecycle

Custom domains progress through the following statuses:

```
pending → dns_verified → ssl_pending → active
                                         │
                                         ├──▶ failed (recoverable)
                                         └──▶ removed (terminal)
```

| Status         | Description                                                   |
| -------------- | ------------------------------------------------------------- |
| `pending`      | Domain added, awaiting DNS verification                       |
| `dns_verified` | TXT record confirmed, SSL provisioning starting               |
| `ssl_pending`  | SSL certificate is being issued by Let's Encrypt              |
| `active`       | Domain is fully operational with valid SSL                    |
| `failed`       | DNS or SSL verification failed (see `last_error` for details) |
| `removed`      | Domain has been deleted from the account                      |

## Verify Domain DNS

Manually trigger a DNS verification check. Useful if you have just added the DNS records and do not want to wait for the automatic check cycle.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://spitshake.io/api/custom_domains/42/verify" \
    -H "X-Auth-Token: YOUR_API_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 — Verified theme={null}
  {
    "id": 42,
    "domain": "sign.yourcompany.com",
    "status": "dns_verified",
    "primary": false,
    "verification_record_name": "_docutrust-verify.sign.yourcompany.com",
    "verification_record_value": "docutrust-verify=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "ssl_status": "pending",
    "dns_verified_at": "2026-04-08T15:20:00Z",
    "ssl_provisioned_at": null,
    "last_checked_at": "2026-04-08T15:20:00Z",
    "last_error": null,
    "created_at": "2026-04-08T15:00:00Z"
  }
  ```

  ```json 200 — Not Yet Verified theme={null}
  {
    "id": 42,
    "domain": "sign.yourcompany.com",
    "status": "pending",
    "primary": false,
    "verification_record_name": "_docutrust-verify.sign.yourcompany.com",
    "verification_record_value": "docutrust-verify=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "ssl_status": "pending",
    "dns_verified_at": null,
    "ssl_provisioned_at": null,
    "last_checked_at": "2026-04-08T15:20:00Z",
    "last_error": "TXT record not found at _docutrust-verify.sign.yourcompany.com. Please check your DNS configuration.",
    "created_at": "2026-04-08T15:00:00Z"
  }
  ```
</ResponseExample>

## List All Domains

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://spitshake.io/api/custom_domains" \
    -H "X-Auth-Token: YOUR_API_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  [
    {
      "id": 42,
      "domain": "sign.yourcompany.com",
      "status": "active",
      "primary": true,
      "verification_record_name": "_docutrust-verify.sign.yourcompany.com",
      "verification_record_value": "docutrust-verify=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
      "ssl_status": "active",
      "dns_verified_at": "2026-04-08T15:20:00Z",
      "ssl_provisioned_at": "2026-04-08T15:22:00Z",
      "last_checked_at": "2026-04-08T16:00:00Z",
      "last_error": null,
      "created_at": "2026-04-08T15:00:00Z"
    },
    {
      "id": 43,
      "domain": "docs.yourcompany.com",
      "status": "pending",
      "primary": false,
      "verification_record_name": "_docutrust-verify.docs.yourcompany.com",
      "verification_record_value": "docutrust-verify=f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3",
      "ssl_status": "pending",
      "dns_verified_at": null,
      "ssl_provisioned_at": null,
      "last_checked_at": null,
      "last_error": null,
      "created_at": "2026-04-08T16:00:00Z"
    }
  ]
  ```
</ResponseExample>

## Set Primary Domain

Designate a domain as the primary. The primary domain is used in all outgoing emails and signing URLs.

<RequestExample>
  ```bash cURL theme={null}
  curl -X PUT "https://spitshake.io/api/custom_domains/42/primary" \
    -H "X-Auth-Token: YOUR_API_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "id": 42,
    "domain": "sign.yourcompany.com",
    "status": "active",
    "primary": true,
    "verification_record_name": "_docutrust-verify.sign.yourcompany.com",
    "verification_record_value": "docutrust-verify=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "ssl_status": "active",
    "dns_verified_at": "2026-04-08T15:20:00Z",
    "ssl_provisioned_at": "2026-04-08T15:22:00Z",
    "last_checked_at": "2026-04-08T16:00:00Z",
    "last_error": null,
    "created_at": "2026-04-08T15:00:00Z"
  }
  ```

  ```json 422 — Domain Not Active theme={null}
  {
    "error": "Only active domains can be set as primary. Current status: dns_verified"
  }
  ```
</ResponseExample>

## Delete a Domain

Remove a custom domain. If the deleted domain was primary, signing URLs revert to `spitshake.io`.

<RequestExample>
  ```bash cURL theme={null}
  curl -X DELETE "https://spitshake.io/api/custom_domains/43" \
    -H "X-Auth-Token: YOUR_API_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "id": 43,
    "domain": "docs.yourcompany.com",
    "status": "removed",
    "primary": false,
    "verification_record_name": "_docutrust-verify.docs.yourcompany.com",
    "verification_record_value": "docutrust-verify=f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3",
    "ssl_status": "pending",
    "dns_verified_at": null,
    "ssl_provisioned_at": null,
    "last_checked_at": null,
    "last_error": null,
    "created_at": "2026-04-08T16:00:00Z"
  }
  ```
</ResponseExample>
