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

# Configure Custom Domain

> Set the Web Frontend and OIDC Backend hosts for an app.

Sets the two custom hosts and starts provisioning. Returns the `CustomDomainStateDto`, including the DNS records to add. See [Custom Domain](/guides/concepts/custom-domain) for the concept and lifecycle.

<Warning>
  This configures **one** custom domain per app. If a custom domain is already configured, this returns `400` — the error message includes the current status. To change it, [delete](/api-reference/workspace/delete-custom-domain) the existing one first, then configure again.
</Warning>

## Request

<ParamField header="Authorization" type="string" required>
  `Bearer <API_KEY>` from Console > Developers > Workspace API Keys.
</ParamField>

<ParamField header="Content-Type" type="string">
  `application/json`
</ParamField>

### Path parameters

<ParamField path="client_id" type="string" required>
  Client identifier of the app.
</ParamField>

### Request body

<ParamField body="webDomain" type="string" required>
  The Web Frontend host (serves the hosted verification UI), e.g. `verify.example.com`. Host only — no scheme or path.
</ParamField>

<ParamField body="oidcDomain" type="string" required>
  The OIDC Backend host (serves the OIDC endpoints), e.g. `connect.example.com`. Host only — no scheme or path.
</ParamField>

## Response

Returns the updated `CustomDomainStateDto`. After a successful configure, the status moves to `awaiting_dns` and the response carries the DNS records to add.

<ResponseField name="webDomain" type="string">
  The configured Web Frontend host.
</ResponseField>

<ResponseField name="oidcDomain" type="string">
  The configured OIDC Backend host.
</ResponseField>

<ResponseField name="status" type="string">
  Lifecycle status. One of `unconfigured`, `awaiting_dns`, `verifying`, `active`, `invalid`.
</ResponseField>

<ResponseField name="requiredAction" type="string">
  What you need to do next. One of `none`, `add_cname`, `waiting`, `verify`, `contact_support`, `retry`.
</ResponseField>

<ResponseField name="statusMessage" type="string">
  Human-readable explanation of the current status. Omitted when there is nothing to report.
</ResponseField>

<ResponseField name="dnsRecords" type="object[]">
  DNS records to add at your DNS provider. See [Get Custom Domain](/api-reference/workspace/get-custom-domain) for each record's fields.
</ResponseField>

<ResponseField name="lastCheckedAt" type="string">
  ISO 8601 timestamp of the most recent verify. Omitted until the first verify runs.
</ResponseField>

<Warning>
  Validation: both hosts are **host-only** (no `https://`, no path). They **must differ** from each other and **must share the same base domain** (for example, both under `example.com`).
</Warning>

<Info>
  Configuring only generates the records — it does not verify them. Add all returned DNS records, then call [Verify Custom Domain](/api-reference/workspace/verify-custom-domain) to advance the status.
</Info>

<RequestExample>
  ```bash theme={null}
  curl -X PUT \
    -H "Authorization: Bearer sk_workspace_test_..." \
    -H "Content-Type: application/json" \
    -d '{"webDomain":"verify.example.com","oidcDomain":"connect.example.com"}' \
    "https://sandbox.api.hopae.com/connect/v1/apps/abc123/custom-domain"
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "webDomain": "verify.example.com",
    "oidcDomain": "connect.example.com",
    "status": "awaiting_dns",
    "requiredAction": "add_cname",
    "statusMessage": "Add the DNS records below, then verify.",
    "dnsRecords": [
      {
        "id": "web-cname",
        "type": "CNAME",
        "host": "verify.example.com",
        "name": "verify.example.com",
        "value": "cname.hopae-edge.com",
        "required": true,
        "description": "Routes your Web Frontend host to the Hopae edge."
      },
      {
        "id": "oidc-cname",
        "type": "CNAME",
        "host": "connect.example.com",
        "name": "connect.example.com",
        "value": "cname.hopae-edge.com",
        "required": true,
        "description": "Routes your OIDC Backend host to the Hopae edge."
      },
      {
        "id": "web-ownership",
        "type": "TXT",
        "host": "verify.example.com",
        "name": "_hopae-verify.verify.example.com",
        "value": "hopae-domain-verification=2b9f8e1c4a7d",
        "required": true,
        "description": "Proves you control the domain."
      }
    ]
  }
  ```
</ResponseExample>
