Attach Custom Domain to Application
curl --request POST \
--url https://api.vertracloud.app/v1/apps/{id}/network/custom \
--header 'Content-Type: application/json' \
--data '
{
"domain": "<string>"
}
'import requests
url = "https://api.vertracloud.app/v1/apps/{id}/network/custom"
payload = { "domain": "<string>" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({domain: '<string>'})
};
fetch('https://api.vertracloud.app/v1/apps/{id}/network/custom', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vertracloud.app/v1/apps/{id}/network/custom",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'domain' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vertracloud.app/v1/apps/{id}/network/custom"
payload := strings.NewReader("{\n \"domain\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vertracloud.app/v1/apps/{id}/network/custom")
.header("Content-Type", "application/json")
.body("{\n \"domain\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vertracloud.app/v1/apps/{id}/network/custom")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"domain\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"response": {
"domain": "example.com"
}
}
Network
Attach Custom Domain to Application
Attaches a custom domain to an application by its ID.
POST
/
v1
/
apps
/
{id}
/
network
/
custom
Attach Custom Domain to Application
curl --request POST \
--url https://api.vertracloud.app/v1/apps/{id}/network/custom \
--header 'Content-Type: application/json' \
--data '
{
"domain": "<string>"
}
'import requests
url = "https://api.vertracloud.app/v1/apps/{id}/network/custom"
payload = { "domain": "<string>" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({domain: '<string>'})
};
fetch('https://api.vertracloud.app/v1/apps/{id}/network/custom', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vertracloud.app/v1/apps/{id}/network/custom",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'domain' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vertracloud.app/v1/apps/{id}/network/custom"
payload := strings.NewReader("{\n \"domain\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vertracloud.app/v1/apps/{id}/network/custom")
.header("Content-Type", "application/json")
.body("{\n \"domain\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vertracloud.app/v1/apps/{id}/network/custom")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"domain\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"response": {
"domain": "example.com"
}
}
string
required
The application ID to attach the custom domain to.
string
If the application belongs to a workspace, the workspace’s ID. Required for workspace members acting on an application they don’t own.
string
required
The custom domain to attach to the application (e.g.,
example.com). Between 1 and 253
characters. A scheme (https://), a path, a port or a leading user@ are stripped before
validation, so https://example.com/path is accepted and stored as example.com.To read the attached domain, call GET /v1/apps/{id}/network/custom, which returns the same
{ "domain" } object (404 NO_CUSTOM_DOMAIN when there is none). To remove a custom domain, call DELETE /v1/apps/{id}/network/custom — sending "@" here is
rejected with INVALID_CUSTOM_DOMAIN_FORMAT.Response
{
"response": {
"domain": "example.com"
}
}
Attaching a domain does not make it live on its own. Publish the DNS records returned by
Custom Domain DNS Records — until the CNAME and the
TXT validation record resolve, the hostname stays
pending_validation.An application holds one custom domain. Sending a different domain replaces the current one:
the new hostname is created and stored first, and only then is the previous one detached — so a
failure never leaves the application without a domain. Sending the domain that is already
attached is idempotent and detaches nothing. The replaced domain stops resolving to the
application, and you are free to attach it elsewhere.
Error Responses
string
The error code indicating the reason for the failure. Possible values:
VALIDATION_ERROR: The path parameter or the body failed validation (400). The response also carriesmessageandpathpointing at the offending field.UNAUTHORIZED: The request is not authenticated (401).USER_NOT_FOUND: The authenticated user could not be resolved (401).APP_NOT_FOUND: The specified application does not exist (404).ACCESS_DENIED: The user does not have permission to act on the application (403).PLAN_DOES_NOT_SUPPORT_CUSTOM_DOMAIN: The owner’s plan does not include custom domains (403).INVALID_CUSTOM_DOMAIN_FORMAT: The value is not a valid domain after normalisation (400).FORBIDDEN_DOMAIN: The domain is on the platform’s blocklist and cannot be attached (400).DOMAIN_ALREADY_IN_USE: The domain is already attached to another application (400).CUSTOM_DOMAIN_REGISTRATION_FAILED: The domain could not be registered right now; retry later (500).INTERNAL_SERVER_ERROR: Unexpected failure (500).
string
A descriptive message providing additional details about the error.
{
"code": "INVALID_CUSTOM_DOMAIN_FORMAT"
}
{
"code": "PLAN_DOES_NOT_SUPPORT_CUSTOM_DOMAIN"
}
{
"code": "APP_NOT_FOUND"
}
A custom domain only works on a published application. If the application is private, turn web
publishing on first with
Publish Application on the Web — and note that
unpublishing removes the custom domain again.
This route has its own budget of 10 requests per minute. See Rate Limiting.