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

# Onboard a workspace

> Walk a new workspace through the onboarding wizard: check status, validate a business domain, confirm it, and complete onboarding.

A freshly created HQ workspace starts **not onboarded**. Until onboarding completes, the workspace can be blocked from normal API access — the onboarding wizard endpoints drive it the rest of the way. This guide walks the flow: read the current status, live-validate a business domain before submit, confirm the domain, and mark onboarding complete.

All requests are authenticated with a personal access token:

```bash theme={null}
export HQ_TOKEN="hq_pat_..."
```

<Note>Setting the domain and completing onboarding require the **admin** scope (`security(("bearer_pat" = ["admin"]))`); a non-admin caller gets a `403`. Reading status and checking a domain only require an authenticated caller.</Note>

## The flow

<Steps>
  <Step title="Check onboarding status">
    Start by reading where the workspace stands. The response tells you what's left to do and which wizard track applies.

    ```bash theme={null}
    curl https://api.hq.zone/v1/api/onboarding/status \
      -H "Authorization: Bearer $HQ_TOKEN"
    # → 200
    # {
    #   "completed": false,
    #   "domain_confirmed": false,
    #   "business_domain": null,
    #   "track": "slack"
    # }
    ```

    Fields:

    * `completed` (bool) — whether onboarding has finished.
    * `domain_confirmed` (bool) — whether the business domain has been confirmed.
    * `business_domain` (string or `null`) — the configured business domain, if any.
    * `track` (string) — the wizard track the SPA should render: `slack`, `teams`, or `web`. It is derived from the workspace's primary corpus source (a `slack` source wins, then `teams`, otherwise `web`).

    See [Get onboarding status](/api-reference/onboarding/onboarding-status).
  </Step>

  <Step title="Live-validate a domain">
    Before submitting, pre-check the value the user typed so a typo is caught early. Pass the candidate as the `domain` query parameter:

    ```bash theme={null}
    curl -G https://api.hq.zone/v1/api/onboarding/domain/check \
      -H "Authorization: Bearer $HQ_TOKEN" \
      --data-urlencode "domain=https://www.acme.com/about"
    # → 200
    # { "valid_format": true, "normalized": "acme.com", "resolves": true }
    ```

    The response reports:

    * `valid_format` (bool) — whether the input normalizes to a usable bare host.
    * `normalized` (string) — the normalized host (scheme, `www.`, path/query stripped, lowercased). Present only when the format is valid.
    * `resolves` (bool) — whether that host resolves to at least one usable public address.

    When the input doesn't look like a domain, the response is just `{ "valid_format": false, "resolves": false }` (no `normalized` field).

    <Tip>The check normalizes before resolving, so `https://www.Acme.com/contact` and `acme.com` both collapse to `acme.com`. A host that resolves only into a private or internal range reports `resolves: false`.</Tip>

    See [Check a domain](/api-reference/onboarding/check-domain).
  </Step>

  <Step title="Set and confirm the domain">
    Once the candidate looks good, submit it. The request body is a single `domain` field:

    ```bash theme={null}
    curl -X POST https://api.hq.zone/v1/api/onboarding/domain \
      -H "Authorization: Bearer $HQ_TOKEN" -H "Content-Type: application/json" \
      -d '{"domain":"acme.com"}'
    # → 200
    # { "ok": true }
    ```

    The server re-normalizes and re-validates the value, then confirms it (this sets `domain_confirmed` in the status) and kicks off a profile crawl of that website. The API is the boundary, so it does not trust the live pre-check:

    * An invalid or unresolvable domain is rejected with `400`.
    * A non-admin caller is rejected with `403`.

    See [Set onboarding domain](/api-reference/onboarding/set-domain).
  </Step>

  <Step title="Complete onboarding">
    Finally, mark the workspace complete. This lifts the onboarding gate that can otherwise block normal API access for a new workspace.

    ```bash theme={null}
    curl -X POST https://api.hq.zone/v1/api/onboarding/complete \
      -H "Authorization: Bearer $HQ_TOKEN"
    # → 200
    # { "ok": true }
    ```

    The call is idempotent — it only stamps the completion time if onboarding wasn't already complete, so calling it twice is safe. A non-admin caller is rejected with `403`.

    See [Complete onboarding](/api-reference/onboarding/complete-onboarding).
  </Step>
</Steps>

## Putting it together

Re-read status after completing to confirm the gate is lifted:

```bash theme={null}
curl https://api.hq.zone/v1/api/onboarding/status \
  -H "Authorization: Bearer $HQ_TOKEN"
# → 200
# { "completed": true, "domain_confirmed": true, "business_domain": "acme.com", "track": "slack" }
```

<Note>`completed: true` is the signal that the workspace is fully onboarded; `domain_confirmed: true` with a non-null `business_domain` reflects a successful domain step.</Note>
