> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/api-reference/advanced/custom-domain.md).

# Custom Domain

## Get custom domain

> State is checked on every read. When it cannot be checked, \`lastCheckedAt\` is null: do not read certificate health from that record. A null status field means unknown.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"CustomDomain"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.configuration.customDomain:read"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"CustomDomainRecord":{"required":["dnsRecords","hostname","isBoundInAzure","isLive","state"],"type":"object","properties":{"hostname":{"type":"string","description":"The hostname, lowercased."},"state":{"description":"Where provisioning has got to.","$ref":"#/components/schemas/CustomDomainState"},"dnsRecords":{"type":"array","items":{"description":"A DNS record the customer creates at their own provider.","$ref":"#/components/schemas/CustomDomainDnsRecord"},"description":"Records the customer must create at their DNS provider. Always both, even once they are in place."},"isLive":{"type":"boolean","description":"True when the tenant's `publicUri` points at this hostname, so end users are sent here."},"isBoundInAzure":{"type":["null","boolean"],"description":"Whether the hostname is bound on the platform. Null when this could not be determined, which does not\nmean the ownership record is missing."},"certificate":{"description":"Certificate detail. Null before a certificate is being issued, and whenever its status could not be read.","$ref":"#/components/schemas/CustomDomainCertificate"},"claimedAt":{"type":["null","string"],"description":"When the hostname was claimed. Null when this could not be determined.","format":"date-time"},"lastCheckedAt":{"type":["null","string"],"description":"When the provisioning status was read to build this record, i.e. the time of the request. Null means the\nstatus could not be read and Neo.Runtime.Security.CustomDomains.CustomDomainRecord.State reflects the tenant configuration only — do not read\ncertificate health from such a record.","format":"date-time"},"diagnostics":{"description":"Raw provisioning detail. Returned only by the GET, to a global administrator; null on every other call,\nincluding the create and activate responses.","$ref":"#/components/schemas/CustomDomainDiagnostics"}},"additionalProperties":false,"description":"One custom domain, as the admin API reports it."},"CustomDomainState":{"enum":["pending_dns","validating","ready","active","failed","deleted"],"type":"string","description":"Where a custom domain is in provisioning."},"CustomDomainDnsRecord":{"type":"object","properties":{"type":{"type":"string","description":"Record type: `CNAME` for routing, `TXT` for ownership verification."},"name":{"type":"string","description":"Record name, fully qualified: the hostname itself for the CNAME, `asuid.` followed by the hostname for\nthe TXT."},"value":{"type":"string","description":"Value to set: the platform's routing target for the CNAME, the ownership verification token for the\nTXT."},"purpose":{"description":"What breaks if it is missing.","$ref":"#/components/schemas/CustomDomainDnsRecordPurpose"}},"additionalProperties":false,"description":"A DNS record the customer creates at their own provider."},"CustomDomainDnsRecordPurpose":{"enum":["routing","ownershipVerification"],"type":"string","description":"What a DNS record the customer must create is for. Each record is checked on its own."},"CustomDomainCertificate":{"type":"object","properties":{"status":{"type":["null","string"],"description":"Raw certificate status (e.g. `active`), for support. Null before one exists."},"expiresOn":{"type":["null","string"],"description":"When the current certificate expires; null until one is issued.","format":"date-time"},"autoRenew":{"type":"boolean","description":"Whether the certificate renews automatically. Renewal requires the customer's DNS records to stay in\nplace."}},"additionalProperties":false,"description":"TLS certificate issued for the hostname."},"CustomDomainDiagnostics":{"type":"object","properties":{"cloudflareId":{"type":["null","string"],"description":"Provider identifier of the custom hostname."},"cloudflareStatus":{"type":["null","string"],"description":"Raw hostname status."},"cloudflareSslStatus":{"type":["null","string"],"description":"Raw certificate status."},"domainControlValidationMethod":{"type":["null","string"],"description":"Domain control validation method: `http` or `txt`."},"originSni":{"type":["null","string"],"description":"Origin SNI hostname, when one is set."},"validationErrors":{"type":"array","items":{"type":"string"},"description":"Raw validation messages. Usually present shortly after creation, until the customer has added their\nrecords."}},"additionalProperties":false,"description":"Raw provisioning detail, for support. Not customer-facing copy."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/customdomain":{"get":{"tags":["CustomDomain"],"summary":"Get custom domain","description":"State is checked on every read. When it cannot be checked, `lastCheckedAt` is null: do not read certificate health from that record. A null status field means unknown.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Custom domain returned.","content":{"text/plain":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}},"application/json":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}},"text/json":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.configuration.customDomain:read</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"404":{"description":"This tenant has no custom domain.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"503":{"description":"Custom domains are not configured on this environment.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Claim domain

> Registers the hostname; the tenant's public address does not change until \`POST /customdomain/activate\`. Refused with 409 when the tenant already has a domain.\
> Example: \`{ "hostname": "registration.brand.com" }\`.\
> Root domains need a DNS provider that supports CNAME flattening, ALIAS or ANAME. Wildcards are rejected. Call \`GET /customdomain/preflight\` to get rejection reasons as codes.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"CustomDomain"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.configuration.customDomain:write"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"AddCustomDomainRequest":{"required":["hostname"],"type":"object","properties":{"hostname":{"minLength":1,"type":"string","description":"Hostname to claim, e.g. `registration.brand.com`. Stored lowercased."}},"additionalProperties":false,"description":"Request body to claim a domain."},"CustomDomainRecord":{"required":["dnsRecords","hostname","isBoundInAzure","isLive","state"],"type":"object","properties":{"hostname":{"type":"string","description":"The hostname, lowercased."},"state":{"description":"Where provisioning has got to.","$ref":"#/components/schemas/CustomDomainState"},"dnsRecords":{"type":"array","items":{"description":"A DNS record the customer creates at their own provider.","$ref":"#/components/schemas/CustomDomainDnsRecord"},"description":"Records the customer must create at their DNS provider. Always both, even once they are in place."},"isLive":{"type":"boolean","description":"True when the tenant's `publicUri` points at this hostname, so end users are sent here."},"isBoundInAzure":{"type":["null","boolean"],"description":"Whether the hostname is bound on the platform. Null when this could not be determined, which does not\nmean the ownership record is missing."},"certificate":{"description":"Certificate detail. Null before a certificate is being issued, and whenever its status could not be read.","$ref":"#/components/schemas/CustomDomainCertificate"},"claimedAt":{"type":["null","string"],"description":"When the hostname was claimed. Null when this could not be determined.","format":"date-time"},"lastCheckedAt":{"type":["null","string"],"description":"When the provisioning status was read to build this record, i.e. the time of the request. Null means the\nstatus could not be read and Neo.Runtime.Security.CustomDomains.CustomDomainRecord.State reflects the tenant configuration only — do not read\ncertificate health from such a record.","format":"date-time"},"diagnostics":{"description":"Raw provisioning detail. Returned only by the GET, to a global administrator; null on every other call,\nincluding the create and activate responses.","$ref":"#/components/schemas/CustomDomainDiagnostics"}},"additionalProperties":false,"description":"One custom domain, as the admin API reports it."},"CustomDomainState":{"enum":["pending_dns","validating","ready","active","failed","deleted"],"type":"string","description":"Where a custom domain is in provisioning."},"CustomDomainDnsRecord":{"type":"object","properties":{"type":{"type":"string","description":"Record type: `CNAME` for routing, `TXT` for ownership verification."},"name":{"type":"string","description":"Record name, fully qualified: the hostname itself for the CNAME, `asuid.` followed by the hostname for\nthe TXT."},"value":{"type":"string","description":"Value to set: the platform's routing target for the CNAME, the ownership verification token for the\nTXT."},"purpose":{"description":"What breaks if it is missing.","$ref":"#/components/schemas/CustomDomainDnsRecordPurpose"}},"additionalProperties":false,"description":"A DNS record the customer creates at their own provider."},"CustomDomainDnsRecordPurpose":{"enum":["routing","ownershipVerification"],"type":"string","description":"What a DNS record the customer must create is for. Each record is checked on its own."},"CustomDomainCertificate":{"type":"object","properties":{"status":{"type":["null","string"],"description":"Raw certificate status (e.g. `active`), for support. Null before one exists."},"expiresOn":{"type":["null","string"],"description":"When the current certificate expires; null until one is issued.","format":"date-time"},"autoRenew":{"type":"boolean","description":"Whether the certificate renews automatically. Renewal requires the customer's DNS records to stay in\nplace."}},"additionalProperties":false,"description":"TLS certificate issued for the hostname."},"CustomDomainDiagnostics":{"type":"object","properties":{"cloudflareId":{"type":["null","string"],"description":"Provider identifier of the custom hostname."},"cloudflareStatus":{"type":["null","string"],"description":"Raw hostname status."},"cloudflareSslStatus":{"type":["null","string"],"description":"Raw certificate status."},"domainControlValidationMethod":{"type":["null","string"],"description":"Domain control validation method: `http` or `txt`."},"originSni":{"type":["null","string"],"description":"Origin SNI hostname, when one is set."},"validationErrors":{"type":"array","items":{"type":"string"},"description":"Raw validation messages. Usually present shortly after creation, until the customer has added their\nrecords."}},"additionalProperties":false,"description":"Raw provisioning detail, for support. Not customer-facing copy."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/customdomain":{"post":{"tags":["CustomDomain"],"summary":"Claim domain","description":"Registers the hostname; the tenant's public address does not change until `POST /customdomain/activate`. Refused with 409 when the tenant already has a domain.\nExample: `{ \"hostname\": \"registration.brand.com\" }`.\nRoot domains need a DNS provider that supports CNAME flattening, ALIAS or ANAME. Wildcards are rejected. Call `GET /customdomain/preflight` to get rejection reasons as codes.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"The hostname to claim.","content":{"application/json":{"schema":{"description":"Request body to claim a domain.","$ref":"#/components/schemas/AddCustomDomainRequest"}},"text/json":{"schema":{"description":"Request body to claim a domain.","$ref":"#/components/schemas/AddCustomDomainRequest"}},"application/*+json":{"schema":{"description":"Request body to claim a domain.","$ref":"#/components/schemas/AddCustomDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain claimed; the body lists the DNS records to create.","content":{"text/plain":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}},"application/json":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}},"text/json":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}}}},"400":{"description":"The hostname cannot be used.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.configuration.customDomain:write</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"409":{"description":"The hostname is in use, or the tenant already has a domain.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"502":{"description":"A provider did not answer; nothing changed, retry.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"503":{"description":"Custom domains are not configured on this environment.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Remove domain

> Reverts the tenant to the platform address, then releases the hostname. Requires \`confirm=true\`, since for a live domain every customer-facing URL reverts.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"CustomDomain"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.configuration.customDomain:write"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/customdomain":{"delete":{"tags":["CustomDomain"],"summary":"Remove domain","description":"Reverts the tenant to the platform address, then releases the hostname. Requires `confirm=true`, since for a live domain every customer-facing URL reverts.","parameters":[{"name":"confirm","in":"query","description":"Must be `true`.","schema":{"type":"boolean"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Domain removed."},"400":{"description":"The confirmation flag was not passed.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.configuration.customDomain:write</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"409":{"description":"This tenant has no custom domain.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"503":{"description":"Custom domains are not configured on this environment.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Activate domain

> Sets the tenant's \`publicUri\` to the domain, changing every customer-facing URL. Refused unless the domain is ready and has passed a recent check.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"CustomDomain"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.configuration.customDomain:write"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"CustomDomainRecord":{"required":["dnsRecords","hostname","isBoundInAzure","isLive","state"],"type":"object","properties":{"hostname":{"type":"string","description":"The hostname, lowercased."},"state":{"description":"Where provisioning has got to.","$ref":"#/components/schemas/CustomDomainState"},"dnsRecords":{"type":"array","items":{"description":"A DNS record the customer creates at their own provider.","$ref":"#/components/schemas/CustomDomainDnsRecord"},"description":"Records the customer must create at their DNS provider. Always both, even once they are in place."},"isLive":{"type":"boolean","description":"True when the tenant's `publicUri` points at this hostname, so end users are sent here."},"isBoundInAzure":{"type":["null","boolean"],"description":"Whether the hostname is bound on the platform. Null when this could not be determined, which does not\nmean the ownership record is missing."},"certificate":{"description":"Certificate detail. Null before a certificate is being issued, and whenever its status could not be read.","$ref":"#/components/schemas/CustomDomainCertificate"},"claimedAt":{"type":["null","string"],"description":"When the hostname was claimed. Null when this could not be determined.","format":"date-time"},"lastCheckedAt":{"type":["null","string"],"description":"When the provisioning status was read to build this record, i.e. the time of the request. Null means the\nstatus could not be read and Neo.Runtime.Security.CustomDomains.CustomDomainRecord.State reflects the tenant configuration only — do not read\ncertificate health from such a record.","format":"date-time"},"diagnostics":{"description":"Raw provisioning detail. Returned only by the GET, to a global administrator; null on every other call,\nincluding the create and activate responses.","$ref":"#/components/schemas/CustomDomainDiagnostics"}},"additionalProperties":false,"description":"One custom domain, as the admin API reports it."},"CustomDomainState":{"enum":["pending_dns","validating","ready","active","failed","deleted"],"type":"string","description":"Where a custom domain is in provisioning."},"CustomDomainDnsRecord":{"type":"object","properties":{"type":{"type":"string","description":"Record type: `CNAME` for routing, `TXT` for ownership verification."},"name":{"type":"string","description":"Record name, fully qualified: the hostname itself for the CNAME, `asuid.` followed by the hostname for\nthe TXT."},"value":{"type":"string","description":"Value to set: the platform's routing target for the CNAME, the ownership verification token for the\nTXT."},"purpose":{"description":"What breaks if it is missing.","$ref":"#/components/schemas/CustomDomainDnsRecordPurpose"}},"additionalProperties":false,"description":"A DNS record the customer creates at their own provider."},"CustomDomainDnsRecordPurpose":{"enum":["routing","ownershipVerification"],"type":"string","description":"What a DNS record the customer must create is for. Each record is checked on its own."},"CustomDomainCertificate":{"type":"object","properties":{"status":{"type":["null","string"],"description":"Raw certificate status (e.g. `active`), for support. Null before one exists."},"expiresOn":{"type":["null","string"],"description":"When the current certificate expires; null until one is issued.","format":"date-time"},"autoRenew":{"type":"boolean","description":"Whether the certificate renews automatically. Renewal requires the customer's DNS records to stay in\nplace."}},"additionalProperties":false,"description":"TLS certificate issued for the hostname."},"CustomDomainDiagnostics":{"type":"object","properties":{"cloudflareId":{"type":["null","string"],"description":"Provider identifier of the custom hostname."},"cloudflareStatus":{"type":["null","string"],"description":"Raw hostname status."},"cloudflareSslStatus":{"type":["null","string"],"description":"Raw certificate status."},"domainControlValidationMethod":{"type":["null","string"],"description":"Domain control validation method: `http` or `txt`."},"originSni":{"type":["null","string"],"description":"Origin SNI hostname, when one is set."},"validationErrors":{"type":"array","items":{"type":"string"},"description":"Raw validation messages. Usually present shortly after creation, until the customer has added their\nrecords."}},"additionalProperties":false,"description":"Raw provisioning detail, for support. Not customer-facing copy."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/customdomain/activate":{"post":{"tags":["CustomDomain"],"summary":"Activate domain","description":"Sets the tenant's `publicUri` to the domain, changing every customer-facing URL. Refused unless the domain is ready and has passed a recent check.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The public address now points at the domain.","content":{"text/plain":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}},"application/json":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}},"text/json":{"schema":{"description":"One custom domain, as the admin API reports it.","$ref":"#/components/schemas/CustomDomainRecord"}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.configuration.customDomain:write</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"409":{"description":"No domain, not ready, or no recent passed check.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"503":{"description":"Custom domains are not configured on this environment.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Check domain

> Requests the hostname from outside and confirms it reaches the platform over HTTPS. Expected to fail while DNS records are missing; the failure code says which step is broken.\
> Requires the write scope, since a passed check is what allows \`POST /customdomain/activate\`.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"CustomDomain"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.configuration.customDomain:write"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"CustomDomainProbeResult":{"type":"object","properties":{"passed":{"type":"boolean","description":"True when an HTTPS request to the hostname reached this application and arrived identified as that\nhostname."},"resolvedHost":{"type":["null","string"],"description":"The host this application reported seeing, when the answer could be read at all; null for an unreachable\nhost, a TLS failure, a timeout or a non-success response. Differs from the hostname on\n`hostNotRewritten`."},"failure":{"description":"Why it did not pass. Null when it did.","$ref":"#/components/schemas/CustomDomainProbeFailure"},"checkedAt":{"type":"string","description":"When the check ran, in UTC.","format":"date-time"}},"additionalProperties":false,"description":"Outcome of one configuration check."},"CustomDomainProbeFailure":{"enum":["unreachable","tlsFailure","differentServer","hostNotRewritten","timeout"],"type":"string","description":"Why a configuration check did not pass."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/customdomain/check":{"post":{"tags":["CustomDomain"],"summary":"Check domain","description":"Requests the hostname from outside and confirms it reaches the platform over HTTPS. Expected to fail while DNS records are missing; the failure code says which step is broken.\nRequires the write scope, since a passed check is what allows `POST /customdomain/activate`.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Check ran; the body says whether it passed and why not.","content":{"text/plain":{"schema":{"description":"Outcome of one configuration check.","$ref":"#/components/schemas/CustomDomainProbeResult"}},"application/json":{"schema":{"description":"Outcome of one configuration check.","$ref":"#/components/schemas/CustomDomainProbeResult"}},"text/json":{"schema":{"description":"Outcome of one configuration check.","$ref":"#/components/schemas/CustomDomainProbeResult"}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.configuration.customDomain:write</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"409":{"description":"This tenant has no custom domain.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"503":{"description":"Custom domains are not configured on this environment.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Preflight hostname

> Reports whether the hostname is in use and, for a root domain, whether the customer's DNS provider can point it at the platform. Writes nothing. An invalid hostname still returns 200, with codes explaining why.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"CustomDomain"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.configuration.customDomain:read"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"CustomDomainPreflight":{"type":"object","properties":{"hostname":{"type":"string","description":"The hostname, lowercased and normalised."},"isValid":{"type":"boolean","description":"False when one of the rules below rejected it."},"rejections":{"type":"array","items":{"description":"Why a hostname was rejected.","$ref":"#/components/schemas/HostnameRejection"},"description":"Which rules rejected it. Empty when it may be used."},"isApex":{"type":"boolean","description":"True when the hostname is the root of its DNS zone. Correct for multi-part suffixes such as\n`brand.co.uk` and for delegated subzones."},"zoneApex":{"type":["null","string"],"description":"Root of the zone the hostname belongs to, when DNS answered."},"dnsProvider":{"type":["null","string"],"description":"Recognised DNS provider, or null when the nameservers are unfamiliar."},"supportsApex":{"type":["null","boolean"],"description":"Whether that provider can point a zone root at a hostname. Null means unknown — show the generic\ncaution, never \"no\"."},"availability":{"description":"Whether the hostname can be claimed.","$ref":"#/components/schemas/CustomDomainAvailability"}},"additionalProperties":false,"description":"What a preflight found out about a hostname."},"HostnameRejection":{"enum":["malformed","tooLong","wildcard","ownDomain"],"type":"string","description":"Why a hostname was rejected."},"CustomDomainAvailability":{"enum":["available","unavailable","claimedByThisTenant","unknown"],"type":"string","description":"Whether a hostname can be claimed."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/customdomain/preflight":{"get":{"tags":["CustomDomain"],"summary":"Preflight hostname","description":"Reports whether the hostname is in use and, for a root domain, whether the customer's DNS provider can point it at the platform. Writes nothing. An invalid hostname still returns 200, with codes explaining why.","parameters":[{"name":"hostname","in":"query","description":"Hostname to check, e.g. `registration.brand.com`.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Preflight completed; the hostname may be invalid.","content":{"text/plain":{"schema":{"description":"What a preflight found out about a hostname.","$ref":"#/components/schemas/CustomDomainPreflight"}},"application/json":{"schema":{"description":"What a preflight found out about a hostname.","$ref":"#/components/schemas/CustomDomainPreflight"}},"text/json":{"schema":{"description":"What a preflight found out about a hostname.","$ref":"#/components/schemas/CustomDomainPreflight"}}}},"400":{"description":"`hostname` is missing.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.configuration.customDomain:read</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"503":{"description":"Custom domains are not configured on this environment.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.thewalletcrew.io/api-reference/advanced/custom-domain.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
