Add a custom domain with the Apps API
Serve an app on your own domain through the Apps API once you prove it is yours with a TXT record and point it at the app.
Every app answers at its platform name. Add a custom domain, such as www.example.com, to serve the app on your own name as well. You prove the domain is yours with a TXT record, point it at the app with a CNAME record, and we issue its certificate.
In the dashboard, the same domains are on the Domains tab of the app's page under App Deployment (Add a domain and protection). This page covers the Apps API, which scripts written for Apps keep using. The hostname in a path is the domain's hostname, such as www.example.com.
Before you begin
Section titled Before you begin- Send your access token as
Authorization: Bearer $CORITAN_TOKEN(Authentication). Each request takes the app'suuid, whichGET /api/v1/client/appslists. - You need a domain whose DNS records you can change at your DNS host. If Coritan hosts its DNS, see Add, edit and delete DNS records.
- For an organization's app, you need the owner or admin role in the organization, and you send the same requests under
/api/v1/orgs/{org_slug}/apps(organization apps reference). - An app can have up to 20 custom domains.
limits.custom_domainsin Regions, sizes and limits gives the number.
The platform name
Section titled The platform nameWhen you create an app, we give it a platform name made of its name on the platform and the platform's app domain, such as web-shop.apps.example.net. It is verified from the start, it goes with the app, and you cannot remove it. The domain list gives it first, with kind platform. Names under the app domain are only given out this way, so you cannot add one as a custom domain. When the platform has no app domain, apps get no platform name and serve only their custom domains.
Add and verify a domain
Section titled Add and verify a domainAdd the hostname with
POST /api/v1/client/apps/{app_uuid}/domains, withouthttps://or a path. Wildcard names such as*.example.comare not accepted.Shellcurl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/domains \ -H "Authorization: Bearer $CORITAN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"hostname": "www.example.com"}'It answers
201with the domain, in the shape List domains shows, withverifiedfalse.Publish the TXT record in the domain's
verificationat your DNS host:DNS_coritan-app.www.example.com. 3600 IN TXT "8b7c1d0e2f3a4b5c6d7e8f9012345678"The name is
_coritan-app.followed by your hostname, and the value is the token we gave the domain.Publish a CNAME record that points the hostname at the domain's
cname_target, the app's platform name:DNSwww.example.com. 3600 IN CNAME web-shop.apps.example.net.At the top of a zone, such as
example.com, a CNAME is not allowed. Use your DNS host's ALIAS record or CNAME flattening to the same target.Ask us to check with
POST /api/v1/client/apps/{app_uuid}/domains/{hostname}/verify:Shellcurl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/domains/www.example.com/verify \ -H "Authorization: Bearer $CORITAN_TOKEN"When we find the TXT record, it answers
{"domain": {...}, "verified": true, "certificates": ["www.example.com"]}, wherecertificatesnames the hostnames whose certificate it ordered, and the domain starts serving the app. When we do not, it answers200with"verified": falseand amessagesaying which record we looked for. Wait a few minutes for DNS to update, then check again.
The domain gets no route until it is verified, so nothing reaches the app on it before then. A domain that is already verified answers "verified": true with an empty certificates, and a check answers 409 with hostname_in_use when another product took the hostname meanwhile. You can remove the TXT record once the domain is verified.
Certificates
Section titled CertificatesA verified domain's certificate is ordered once the app has replicas serving it. Its certificate moves from none to pending to issued. The certificate authority checks the domain over HTTP, so the CNAME record from step 3 must be in place for the certificate to be issued.
A hostname in use elsewhere
Section titled A hostname in use elsewhereA hostname can belong to one app at a time. Another app that is still verifying a hostname holds it for 72 hours after adding it. After that, the next app that adds the hostname takes it over. A hostname that another app has verified, or that another product on the platform serves, such as a web proxy, cannot be added.
List domains
Section titled List domainsGET /api/v1/client/apps/{app_uuid}/domains lists the platform name first, then the custom domains:
curl https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/domains \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"domains": [
{
"hostname": "web-shop.apps.example.net",
"kind": "platform",
"verified": true,
"verified_at": "2026-09-20T09:12:00Z",
"created_at": "2026-09-20T09:12:00Z",
"url": "https://web-shop.apps.example.net",
"certificate": "issued",
"verification": null,
"cname_target": null
},
{
"hostname": "www.example.com",
"kind": "custom",
"verified": false,
"verified_at": null,
"created_at": "2026-09-26T10:05:00Z",
"url": null,
"certificate": "none",
"verification": {"type": "TXT", "name": "_coritan-app.www.example.com", "value": "8b7c1d0e2f3a4b5c6d7e8f9012345678"},
"cname_target": "web-shop.apps.example.net"
}
]
}
kind is platform or custom. url is null until the domain is verified. certificate is none, pending or issued. verification is the TXT record to publish, and null once the domain is verified. cname_target is where a custom domain points, and null for the platform name.
Remove a domain
Section titled Remove a domainRemoving a custom domain stops it reaching the app at once, and deletes its route and certificate. The records at your DNS host stay until you delete them.
DELETE /api/v1/client/apps/{app_uuid}/domains/{hostname} removes a custom domain and answers {"deleted": "www.example.com"}. The platform name answers 409 with {"error": "platform_domain", "message": "The platform name goes with the deployment and cannot be removed"}, and a hostname the app does not have answers 404 with Domain not found.
Result
Section titled ResultThe domain is verified, and its certificate is issued once the certificate authority has checked it. Visitors reach the app at https://www.example.com, and the domain shows Verified on the app's Domains tab.
Troubleshooting
Section titled Troubleshooting| Status | detail |
Cause |
|---|---|---|
409 |
{"error": "domain_exists", "message": "That hostname is already added to this deployment"} |
The app has it already. |
409 |
{"error": "hostname_in_use", "message": "That hostname is in use on the platform"} |
Another app has verified it or added it less than 72 hours ago, or another product serves it. If it is yours, remove it there first. |
409 |
{"error": "domain_limit", "message": "A deployment can have at most 20 custom domains"} |
The app has 20 custom domains. Remove one it no longer needs. |
422 |
{"message": "Give the hostname alone, without http:// or a path", "field": "hostname"} |
hostname starts with http:// or https://. |
422 |
{"message": "'*.example.com' is not a hostname", "field": "hostname"} |
hostname is not a hostname. |
422 |
{"message": "Names under apps.example.net are given to deployments by the platform", "field": "hostname"} |
The name is under the app domain. Each app gets its own name there when it is created. |
429 |
Too many checks for this app. Wait a few minutes; DNS changes take a while anyway. |
The app asked for 30 checks in the last 10 minutes. |
No TXT record at _coritan-app.www.example.com holds the token yet. DNS changes can take a few minutes to appear.- The
messageof a check that found no record. The record is not published yet, or holds another value. Check its name and value at your DNS host, wait a few minutes, then check again. - The certificate stays
pending - The hostname does not point at the app yet. Check the CNAME record, or the ALIAS record at the top of a zone.
Related
Section titled Related- How the Apps API runs an app
- Add, edit and delete DNS records
- Apps API limits
- Add a domain and protection, for the same in the dashboard
API operations on this page
| Method | Path | What it does |
|---|---|---|
GET | /api/v1/client/apps/{app_uuid}/domains | List an app's domains: its platform name first, then its custom domains |
POST | /api/v1/client/apps/{app_uuid}/domains | Add a custom domain |
DELETE | /api/v1/client/apps/{app_uuid}/domains/{hostname} | Remove a custom domain from an app |
POST | /api/v1/client/apps/{app_uuid}/domains/{hostname}/verify | Look for the domain's TXT record |
GET | /api/v1/orgs/{org_slug}/apps/{app_uuid}/domains | List an app's domains: its platform name first, then its custom domains |
POST | /api/v1/orgs/{org_slug}/apps/{app_uuid}/domains | Add a custom domain |
DELETE | /api/v1/orgs/{org_slug}/apps/{app_uuid}/domains/{hostname} | Remove a custom domain from an app |
POST | /api/v1/orgs/{org_slug}/apps/{app_uuid}/domains/{hostname}/verify | Look for the domain's TXT record |