This documentation is currently under development. Certain sections are not yet complete and will be added shortly.
For the complete documentation index, see llms.txt. This page is also available as Markdown.

Custom Domain

Get the tenant's custom domain

get
/api/{tenantId}/admin/customdomain

The state is current on every read, so a domain the customer fixed days later reports correctly with no other call. Reading changes nothing.

When the state cannot be checked the record still comes back, with a null lastCheckedAt — do not read certificate health from such a record. A null isBoundInAzure likewise means unknown, not a confirmed absence.

diagnostics is populated for global administrators only.

Required scopes
This endpoint requires the following scopes:
Authorizations
OAuth2implicitRequired
Authorization URL:
Path parameters
tenantIdstringRequired
Responses
200

The tenant's custom domain.

One custom domain, as the admin API reports it.

hostnamestringRequired

The hostname, lowercased.

statestring · enumRequired

Where provisioning has got to.

Possible values:
isLivebooleanRequired

True when the tenant's publicUri points at this hostname, so end users are sent here.

isBoundInAzureboolean · nullableRequired

Whether the hostname is bound on the platform. Null when this could not be determined, which does not mean the ownership record is missing.

claimedAtstring · nullableOptional

When the hostname was claimed. Null when this could not be determined.

lastCheckedAtstring · nullableOptional

When the provisioning status was read to build this record, i.e. the time of the request. Null means the status could not be read and Neo.Runtime.Security.CustomDomains.CustomDomainRecord.State reflects the tenant configuration only — do not read certificate health from such a record.

get/api/{tenantId}/admin/customdomain
GET /api/{tenantId}/admin/customdomain HTTP/1.1
Host: app.neostore.cloud
Authorization: Bearer YOUR_OAUTH2_TOKEN
Accept: */*
{
  "hostname": "text",
  "state": "pending_dns",
  "dnsRecords": [
    {
      "type": "text",
      "name": "text",
      "value": "text",
      "purpose": "routing"
    }
  ],
  "isLive": true,
  "isBoundInAzure": null,
  "certificate": {
    "status": null,
    "expiresOn": null,
    "autoRenew": true
  },
  "claimedAt": null,
  "lastCheckedAt": null,
  "diagnostics": {
    "cloudflareId": null,
    "cloudflareStatus": null,
    "cloudflareSslStatus": null,
    "domainControlValidationMethod": null,
    "originSni": null,
    "validationErrors": [
      "text"
    ]
  }
}

Claim a domain

post
/api/{tenantId}/admin/customdomain

Registers the hostname and records it as claimed. Nothing about the tenant's public address changes — that needs a separate call to activate.

Refused with 409 when the tenant already has a different domain: a tenant has one public address, so replace a domain by removing it, then adding the new one.

Root domains are accepted; they need a DNS provider that can flatten them (CNAME flattening, ALIAS or ANAME), which is the customer's to check. Wildcards are rejected.

Call GET preflight first if you need to know why a hostname is unusable — this action reports a rejection as a 400 for a human to read, not as codes to branch on.

Required scopes
This endpoint requires the following scopes:
Authorizations
OAuth2implicitRequired
Authorization URL:
Path parameters
tenantIdstringRequired
Body

Request body to claim a domain.

hostnamestring · min: 1Required

Hostname to claim, for example registration.brand.com. Lowercased server-side.

Responses
201

Domain claimed. The response says which DNS records the customer must create.

One custom domain, as the admin API reports it.

hostnamestringRequired

The hostname, lowercased.

statestring · enumRequired

Where provisioning has got to.

Possible values:
isLivebooleanRequired

True when the tenant's publicUri points at this hostname, so end users are sent here.

isBoundInAzureboolean · nullableRequired

Whether the hostname is bound on the platform. Null when this could not be determined, which does not mean the ownership record is missing.

claimedAtstring · nullableOptional

When the hostname was claimed. Null when this could not be determined.

lastCheckedAtstring · nullableOptional

When the provisioning status was read to build this record, i.e. the time of the request. Null means the status could not be read and Neo.Runtime.Security.CustomDomains.CustomDomainRecord.State reflects the tenant configuration only — do not read certificate health from such a record.

post/api/{tenantId}/admin/customdomain
POST /api/{tenantId}/admin/customdomain HTTP/1.1
Host: app.neostore.cloud
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 19

{
  "hostname": "text"
}
{
  "hostname": "text",
  "state": "pending_dns",
  "dnsRecords": [
    {
      "type": "text",
      "name": "text",
      "value": "text",
      "purpose": "routing"
    }
  ],
  "isLive": true,
  "isBoundInAzure": null,
  "certificate": {
    "status": null,
    "expiresOn": null,
    "autoRenew": true
  },
  "claimedAt": null,
  "lastCheckedAt": null,
  "diagnostics": {
    "cloudflareId": null,
    "cloudflareStatus": null,
    "cloudflareSslStatus": null,
    "domainControlValidationMethod": null,
    "originSni": null,
    "validationErrors": [
      "text"
    ]
  }
}

Remove the domain

delete
/api/{tenantId}/admin/customdomain

Puts the tenant back on the platform's own address, then releases the hostname.

Requires confirm=true, because for a live domain this reverts every customer-facing URL.

Required scopes
This endpoint requires the following scopes:
Authorizations
OAuth2implicitRequired
Authorization URL:
Path parameters
tenantIdstringRequired
Query parameters
confirmbooleanOptional

Must be true; acknowledges that a live domain's customer-facing URLs revert.

Responses
204

Domain removed.

No content

delete/api/{tenantId}/admin/customdomain
DELETE /api/{tenantId}/admin/customdomain HTTP/1.1
Host: app.neostore.cloud
Authorization: Bearer YOUR_OAUTH2_TOKEN
Accept: */*

No content

Switch the tenant's public address to the domain

post
/api/{tenantId}/admin/customdomain/activate

The only call that changes what customers see: sets the tenant's publicUri to the domain.

Refused unless the domain is ready and a check has passed for it recently.

Required scopes
This endpoint requires the following scopes:
Authorizations
OAuth2implicitRequired
Authorization URL:
Path parameters
tenantIdstringRequired
Responses
200

The tenant's public address now points at the domain.

One custom domain, as the admin API reports it.

hostnamestringRequired

The hostname, lowercased.

statestring · enumRequired

Where provisioning has got to.

Possible values:
isLivebooleanRequired

True when the tenant's publicUri points at this hostname, so end users are sent here.

isBoundInAzureboolean · nullableRequired

Whether the hostname is bound on the platform. Null when this could not be determined, which does not mean the ownership record is missing.

claimedAtstring · nullableOptional

When the hostname was claimed. Null when this could not be determined.

lastCheckedAtstring · nullableOptional

When the provisioning status was read to build this record, i.e. the time of the request. Null means the status could not be read and Neo.Runtime.Security.CustomDomains.CustomDomainRecord.State reflects the tenant configuration only — do not read certificate health from such a record.

post/api/{tenantId}/admin/customdomain/activate
POST /api/{tenantId}/admin/customdomain/activate HTTP/1.1
Host: app.neostore.cloud
Authorization: Bearer YOUR_OAUTH2_TOKEN
Accept: */*
{
  "hostname": "text",
  "state": "pending_dns",
  "dnsRecords": [
    {
      "type": "text",
      "name": "text",
      "value": "text",
      "purpose": "routing"
    }
  ],
  "isLive": true,
  "isBoundInAzure": null,
  "certificate": {
    "status": null,
    "expiresOn": null,
    "autoRenew": true
  },
  "claimedAt": null,
  "lastCheckedAt": null,
  "diagnostics": {
    "cloudflareId": null,
    "cloudflareStatus": null,
    "cloudflareSslStatus": null,
    "domainControlValidationMethod": null,
    "originSni": null,
    "validationErrors": [
      "text"
    ]
  }
}

Check that the domain reaches this application

post
/api/{tenantId}/admin/customdomain/check

Calls the hostname from the outside and confirms the request arrives here identified as that hostname. One call exercises the customer's DNS, the certificate, and the platform accepting the hostname.

Expected to fail while the customer still has records to add — the failure code says which link in the chain is broken, which is the point of running it early.

Requires the write scope: the check can complete the domain's setup before testing it.

Required scopes
This endpoint requires the following scopes:
Authorizations
OAuth2implicitRequired
Authorization URL:
Path parameters
tenantIdstringRequired
Responses
200

Check ran. The body says whether it passed and, if not, why.

Outcome of one configuration check.

passedbooleanOptional

True when an HTTPS request to the hostname reached this application and arrived identified as that hostname.

resolvedHoststring · nullableOptional

The host this application reported seeing, when the answer could be read at all; null for an unreachable host, a TLS failure, a timeout or a non-success response. Differs from the hostname on hostNotRewritten.

failurestring · enumOptional

Why it did not pass. Null when it did.

Possible values:
checkedAtstring · date-timeOptional

When the check ran, in UTC.

post/api/{tenantId}/admin/customdomain/check
POST /api/{tenantId}/admin/customdomain/check HTTP/1.1
Host: app.neostore.cloud
Authorization: Bearer YOUR_OAUTH2_TOKEN
Accept: */*
{
  "passed": true,
  "resolvedHost": null,
  "failure": "unreachable",
  "checkedAt": "2026-01-01T00:00:00.000Z"
}

Check a hostname before claiming it

get
/api/{tenantId}/admin/customdomain/preflight

Answers the two questions the add screen cannot answer on its own: whether the hostname is already in use, and — for a root domain — whether the customer's DNS provider can even point it at us. Creates nothing and writes nothing.

The apex verdict is correct for brand.co.uk and for a delegated subzone.

An invalid hostname is still a 200: the point is to report what is wrong with it, in codes the caller can translate.

Required scopes
This endpoint requires the following scopes:
Authorizations
OAuth2implicitRequired
Authorization URL:
Path parameters
tenantIdstringRequired
Query parameters
hostnamestringRequired

Hostname the customer intends to claim, for example registration.brand.com.

Responses
200

Preflight completed. A hostname may be invalid and still return 200.

What a preflight found out about a hostname.

hostnamestringOptional

The hostname, lowercased and normalised.

isValidbooleanOptional

False when one of the rules below rejected it.

isApexbooleanOptional

True when the hostname is the root of its DNS zone. Correct for multi-part suffixes such as brand.co.uk and for delegated subzones.

zoneApexstring · nullableOptional

Root of the zone the hostname belongs to, when DNS answered.

dnsProviderstring · nullableOptional

Recognised DNS provider, or null when the nameservers are unfamiliar.

supportsApexboolean · nullableOptional

Whether that provider can point a zone root at a hostname. Null means unknown — show the generic caution, never "no".

availabilitystring · enumOptional

Whether the hostname can be claimed.

Possible values:
get/api/{tenantId}/admin/customdomain/preflight
GET /api/{tenantId}/admin/customdomain/preflight?hostname=text HTTP/1.1
Host: app.neostore.cloud
Authorization: Bearer YOUR_OAUTH2_TOKEN
Accept: */*
{
  "hostname": "text",
  "isValid": true,
  "rejections": [
    "malformed"
  ],
  "isApex": true,
  "zoneApex": null,
  "dnsProvider": null,
  "supportsApex": null,
  "availability": "available"
}

Last updated