REST API: custom domains
Attach, verify, and route a custom domain for an agent's public surfaces.
A custom domain lets an agent's public-facing surface, such as its Help Center, appear under your own hostname instead of an AgentStack subdomain. List an agent's domains, then add one with the hostname you control. Adding a domain does not make it live: you must complete DNS and SSL verification before it serves traffic.
After you add a domain, configure the DNS records AgentStack requires at your registrar or DNS provider, then call POST /custom-domains/{domainId}/verify to re-check status. Verification is asynchronous on AgentStack's side too — DNS propagation and certificate issuance take time, so poll verification with bounded backoff rather than a tight loop, and do not assume a single verify call finishing means traffic is already routing.
PATCH /custom-domains/{domainId}/surface changes which public surface, such as the Help Center or the embed, a verified domain routes to. Only change the surface after confirming the domain is verified, since routing an unverified domain does not make it reachable.
Removing a custom domain is a routing change with a customer-facing impact: any link or bookmark using that hostname stops resolving to the agent's surface immediately. Confirm the domain is no longer referenced anywhere public before you delete it.
DELETE /custom-domains/{domainId} and PATCH /custom-domains/{domainId}/surface read the agent that owns the domain. When that agent waits for deletion, both answer 410 AGENT_UNAVAILABLE and change nothing. To remove the hostname before the deletion completes, call POST /agents/{id}/cancel-delete first, then delete the domain.
Refusals on add
POST /agents/{id}/custom-domains checks four rules before it attaches the hostname to the platform, so a refusal never leaves a partial domain behind. Match on the error code, not on the status.
409 HOSTNAME_TAKEN— another agent in your organization already holds this hostname, or another organization holds it. AgentStack refuses the add rather than repointing the domain that exists.409 EMAIL_RECEIVING_CONFLICT— this hostname already receives email for your organization. Receiving publishes an MX record at the hostname itself, and a web domain needs a CNAME at that same name. DNS does not permit a CNAME beside another record, so the pair cannot work. Disable receiving on that hostname first, or use a different one.403 PLAN_REQUIRED— your organization does not hold the Custom Domain add-on. The add-on is the entitlement, and the plan tier only sizes the allowance, so a plan change alone does not clear this refusal.403 DOMAIN_LIMIT_REACHED— the organization holds its full allowance of web domains. The allowance counts every agent together. Remove a domain, then retry.
The same MX-versus-CNAME rule guards the other direction. Both receiving doors, POST /channels/email/domains/{domainId}/receiving/request and POST /channels/email/domains/{domainId}/receiving/verify, answer 409 WEB_DOMAIN_CONFLICT when a web domain already occupies the hostname. To read every hostname your organization uses, with any conflict that was created before these rules existed, use GET /domains.