Create domains

Attaches a hostname — instantly if you already own it, otherwise with a DNS challenge.

POST /v1/platform/projects/{project}/apps/{app}/domains

Addresshttps://api.hanzo.ai/v1/platform/projects/{project}/apps/{app}/domains
MethodPOST
Operationpost_platform_projects_by_project_apps_by_app_domains
AuthAuthorization: Bearer $HANZO_API_KEY

Attaches a hostname — instantly if you already own it, otherwise with a DNS challenge.

It attaches host to the app, and which of two things happens depends on who owns the name. A host inside the caller org's own subtree is structurally owned, so it goes ACTIVE immediately and answers 201. A bring-your-own host is claimed as PENDING and answers the DNS challenge records to publish; it is NOT rendered into the app's ingress until /verify passes.

Claims are globally unique. A host already claimed by another organization is 409, and so is one claimed by a different app in your own; re-adding this app's OWN claim is idempotent and answers its current state at 200. The default host is always attached and re-adding it is 409. A host under the platform's shared apex that is not the caller's own subtree is 403 — it belongs to whoever owns that subtree and can never be grabbed through the custom path.

host must be a valid DNS hostname; anything else is 400. Requires a validated principal; 401 without one.

Request

5 fields, body application/json (required).

FieldInTypeRequiredDescription
projectpathstringyesProject is the project the application lives under, from the path.
apppathstringyesApp is the application's slug, from the path.
appbodystring—App is the application's slug, from the path.
hostbodystring—Host is the hostname to attach.
projectbodystring—Project is the project the application lives under, from the path.

Response

StatusBodyMeaning
200platform.domainViewok
201platform.domainViewcreated
defaultproblem-detailsrefused

200 body — 12 fields.

FieldInTypeAlwaysDescription
createdAtbodyinteger (int64)—CreatedAt is the unix second the custom claim was made.
detailbodystring—Detail says why a claim is still pending, in the resolver's own words.
hostbodystring—Host is the hostname itself.
kindbodystring—Kind is default, subtree or custom — how the org came to own it.
primarybodyboolean—Primary marks the app's permanent default host.
recordsbodyplatform.Record[]—Records are the DNS records to publish while a custom claim is pending.
records[].namebodystring—the record name the customer creates
records[].typebodystring—TXT | CNAME
records[].valuebodystring—the record value
statusbodystring—Status is live, provisioning, pending_deploy or pending, derived from the operator CR and never fabricated.
urlbodystring—URL is the host as an HTTPS address.
verifiedbodyboolean—Verified is whether ownership is settled — always true for a host the org structurally owns.

Failure carries the platform error shape — see Errors.

Examples

hanzo platform projects apps domains create <project> <app>
import { Configuration, PlatformApi } from 'hanzoai';

const api = new PlatformApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postPlatformProjectsByProjectAppsByAppDomains({ project: 'project', app: 'app', app: "<app>", host: "<host>" });
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import PlatformApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = PlatformApi(client).post_platform_projects_by_project_apps_by_app_domains(project='project', app='app', app="<app>", host="<host>")
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.PlatformAPI.PostPlatformProjectsByProjectAppsByAppDomains(context.Background()).Execute()
if err != nil {
	return err
}
use hanzo_client::apis::{configuration::Configuration, platform_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = platform_api::post_platform_projects_by_project_apps_by_app_domains(&cfg, Default::default()).await?;
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.PlatformApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new PlatformApi(client).postPlatformProjectsByProjectAppsByAppDomains();
curl -X POST https://api.hanzo.ai/v1/platform/projects/<project>/apps/<app>/domains \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "app": "<app>",
       "host": "<host>"
     }'

MCP reaches platform through the platform tool, which names its 38 operations with its own verbs — this one among them, under a name only MCP declares. describe explains any of them:

curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "get_build"
         }
       }
     }'

Platform API · All Hanzo APIs · Interactive reference

Was this page useful?