---
title: "Register an IP and mint a hostname"
method: POST
path: "/v1/hostnames"
tags: ["hostnames"]
---

# Register an IP and mint a hostname

`POST /v1/hostnames`

## Request

- Base URL: `https://dnsmint.com/api`
- URL: `https://dnsmint.com/api/v1/hostnames`
- Auth: HTTP bearer

Registers an IPv4 or IPv6 address and returns a new hostname. The subdomain is opaque unless you pass one, and lands on a domain assigned to your account. An account holding more than one may choose which. Public, private, and reserved addresses on every plan; the address a hostname is minted with fixes its address class for life. New registrations may briefly return "pending"; poll GET until "live". Request bodies are capped at 4KB. Plans that include custom subdomains may pass one. Any account may pass an optional dedicated domain, which must be one it already holds.

## Request body

- CreateHostnameRequest
  - `ip` string: An IPv4 or IPv6 address, public or private. Private and reserved ranges are accepted on every plan. Send either ip or target, not both. The address a hostname is minted with fixes its address class for life. A hostname keeps the address class it was minted with. Repointing within a class is free, including between A and AAAA; crossing from public to private or private to public returns 409. This blocks DNS rebinding, where one origin is public first, to deliver a payload under a trusted certificate, and private second, to read a response from inside the visitor's network. Release the hostname and mint a new one for the other class.
  - `target` string: A platform endpoint to follow instead of an address, for a platform that gives you a URL and no IP. We resolve it and publish ordinary A or AAAA records, then re-resolve within the target's TTL and follow it as it moves. Send either ip or target, not both. What the target answers fixes the hostname's address class exactly as an ip would, and a target that later answers outside that class is refused and the last address stays served. A target answering both public and private addresses is refused as ambiguous.
  - `subdomain` string: Optional custom subdomain, on every plan. 3-63 lowercase letters, digits, and hyphens; no periods; no leading or trailing hyphen. Duplicate or retired subdomains return 409.
  - `domain` string: Optional dedicated domain. Must already be assigned to the team. Omitted, one of the team's dedicated domains is chosen.
  - `certificate` 'self' | 'csr' | 'managed': Who holds the private key, and with it who runs the ACME client. "self" means you do all of it: run an ACME client against the DNS-01 API, pick your own CA, and we never see key material. "csr" means you keep the key and we run the protocol: register, then POST a certificate request to /v1/hostnames/{id}/certificate. Renewal is yours there, because we hold no key to build a replacement from. "managed" means we generate the key, run ACME, and renew before expiry on a fresh key each time; you pull the current pair from GET /v1/hostnames/{id}/certificate. See Certificate modes.
  - `ca` 'letsencrypt' | 'google': Which certificate authority issues, for certificate: "managed" and certificate: "csr" - the modes where we run the ACME client. Sending it with "self" returns 400: you run the client there, so the CA is a choice you make in it. Omitted, we pick - Let's Encrypt unless it has recently rate-limited orders for your domain and another CA is configured. Renewals always return to the CA that issued, because the ACME Renewal Information identifier is only resolvable by that CA. See https://dnsmint.com/ca

## Response `201`

Hostname created.

- HostView: A hostname. Where it points is deliberately not here: `ip`, `record_type` and the target are either something you just sent or something DNS answers authoritatively, and a second copy in this body can only disagree with it. Ask /v1/hostnames/{id}/diagnose for where it points and what we observed, with the time we observed it.
  - `id` string, required: Opaque identifier used in the /v1/hostnames/{id} paths.
  - `hostname` string, required: The fully qualified hostname: an opaque subdomain on a domain assigned to your account.
  - `status` 'pending' | 'live' | 'released' | 'suspended' | 'terminated', required: pending: registered, not yet confirmed on the nameservers. live: the record is served, and it stays so until you release it. released: you released it; writes return 409 and the subdomain can be minted again as a new hostname. suspended: held while an abuse report is reviewed; it stops resolving and writes return 403, but nothing is lost if the report is not upheld. terminated: an abuse report was upheld, not reversible. New registrations may briefly return pending; poll GET until live.
  - `certificate` 'self' | 'csr' | 'managed', required: Who holds the private key. self: you, and you run the ACME client. csr: you hold the key and we run the protocol around your signed request. managed: we generate the key, obtain and renew the certificate, and keep a copy for you to fetch.
  - `created_at` string, date-time, required: When the hostname was registered.

## Other responses

- `400`: Invalid JSON, missing both "ip" and "target" or sending both, syntactically invalid IP address, invalid subdomain or domain, or body over 4KB.
- `401`: The Authorization header is missing, malformed, or the key is unknown or revoked.
- `402`: No domain to mint on yet. Either signup is unfinished (no card on file), or the team's domain is still being set up: then the error says so and Retry-After says when to ask again, and the team owner is emailed when it is ready.
- `403`: The API key does not carry the scope this call needs, or its grant does not reach the hostname being minted.
- `409`: Told apart by the error code. CONFLICT: the requested subdomain is taken or retired on this domain. DOMAIN_PROVISIONING: a domain for this team is still being set up; carries Retry-After and a Location pointing at the provisioning status. NO_DOMAIN_AVAILABLE: no domain is assigned yet; it is being set up and the team owner is emailed when it is ready, so a timed retry will not help.
- `429`: The account is at its hostname cap, or has made more than 30 registrations in a minute.
- `500`: Unexpected server error.
- `501`: A valid request this deployment cannot serve. Returned for certificate: "managed" where no certificate encryption key is configured. Retry later; do not change the request.

---

[API](https://skmtc.dev/dnsmint/apis/dnsmint-api.md) · [All operations](https://skmtc.dev/dnsmint/apis/dnsmint-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dnsmint/apis/dnsmint-api/revisions/98fb1f87725a?raw)
