# Hosted white-label

Source: https://ceyo.ai/docs/signal/hosted-white-label-guides

### Hosted white-label

Configure a branded hosted experience, serve it from your own domain, provision customer access, and send customers into the correct project or location.

### Configure white-label

Open the workspace in Signal, go to **Settings → White label**, and enable Hosted white label. Add the platform name, logo, favicon, bundled font, color palette, shape, text size, density, return destination, and return action text. Then choose which project and location navigation items customers can see.

**Preview before enabling access**

Use Preview to verify branding, navigation, landing behavior, and role-based controls.

**Hosted access switch**

Hosted white label must remain enabled to create or redeem login links and to keep hosted customer sessions active.

**Return behavior**

Set a workspace default return URL, or provide a per-link `return_url` that uses an origin allowed by the issuing API key.

### Add a custom domain

Serve the hosted experience from your own hostname, such as `ai.yourcompany.com`, instead of Signal's address. Everything your customers load in the browser, including the login links you send them, stays on your domain, and Signal issues and renews the TLS certificate for you. Your backend keeps calling the public API at `api.signal.ceyo.ai` as before. Go to **Settings → White label → Custom domain**, enter the hostname, and create the CNAME record the card shows you.

```dns
# Create this record at your DNS provider. Use the exact target shown in Signal.
ai.yourcompany.com.    CNAME    domains.signal.ceyo.ai.

# Check propagation from your terminal.
dig +short CNAME ai.yourcompany.com
# domains.signal.ceyo.ai.
```

**Use a subdomain**

Apex domains such as `yourcompany.com` cannot carry a CNAME and are not supported. Do not add A or AAAA records for the hostname.

**Cloudflare and other proxies**

Set the record to **DNS only** (grey cloud). A proxied record answers with the proxy's own addresses instead of the CNAME, so the certificate cannot be issued. Signal detects this and warns you on the card.

**Activation**

The card tracks four steps: DNS record points at Signal, TLS certificate issued, hostname verified end to end, domain active. Expect a few minutes after DNS propagates. Requests that are not verified within 7 days expire, and failed steps show the reason with a Retry action.

**Sign-in on your domain**

Customers reach your domain only through login links created by your application; there is no Signal sign-in page there. Sessions started on your domain are valid only on your domain.

**Replacing or removing**

To move to a new hostname, add it and the previous one is retired automatically once the new domain is active and outstanding login links have expired. Remove ends every session on the hostname immediately; your branding is kept.

### Provision customer access

Use active project and location packages, stable external IDs, and a workspace API key. Create the resources, upsert an embedded identity, then grant that identity access to the required project or location. Viewer is read-only, editor manages supported operational features, and admin additionally manages general settings.

```curl
# Create the customer project and optional location.
curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/projects' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{"name":"Acme","external_id":"customer-project","package_id":"{package_id}"}'

curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/projects/customer-project/locations' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{"name":"Acme London","external_id":"customer-location","package_id":"{location_package_id}"}'

# Upsert the customer identity and grant project access.
curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/embedded-identities/customer-user-42' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{"name":"Customer User"}'

curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/embedded-identities/customer-user-42/projects/customer-project/access' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{"role":"viewer"}'
```

### Create hosted login links

Create links from your backend with a key that has `login_links:manage`. Each URL is short-lived, one-time, and scoped to the embedded identity's existing grant.

```curl
curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/login-links' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
    "external_user_id": "customer-user-42",
    "project_id": "customer-project",
    "landing": "auto",
    "return_url": "https://portal.partner.example/customers/42",
    "expires_in": 900
  }'
```

**Common destinations**

Use `landing` with `auto`, `projects`, or `locations`. Use `redirect_path` instead when you need a specific internal page.

**Lifecycle**

Inspect a link with `GET /login-links/{login_link_id}` or revoke a pending link with `DELETE` on the same path.
