Skip to main content
Neon Postgres Docs

Search documentation

Type to search this documentation.

Register a custom domain on a branch

POST/projects/{project_id}/branches/{branch_id}/custom-domainsRegister a custom domain on a branch

Registers a customer-owned domain (for example dashboard.acme.com) on the branch and points it at a target entity, chosen by entity_type + entity_id. In v1 only entity_type: function is supported (an unsupported type is rejected with 400), where entity_id is the function slug and the function must already exist on the branch (else 404).

The response includes the cname_target the customer must point their domain at with a CNAME record; the domain goes live only once that DNS resolves and a certificate is issued on the first request. A domain already registered to another resource is rejected with 409 and no detail about the owner. Re-registering the same domain for the same entity is idempotent.

Note: This endpoint is currently in Beta.

Parameters

project_idstringpathrequired

The Neon project ID

pattern ^[a-z0-9-]{1,60}$

branch_idstringpathrequired

The Neon branch ID

pattern ^[a-z0-9-]{1,60}$

Request body

required
application/json
objectCustomDomainRegisterRequest
domainstringrequired

The custom domain to register (for example `dashboard.acme.com`). Case-insensitive; normalized to lowercase (a trailing root dot is stripped, so the 254-char bound admits a fully-qualified name whose normalized form is 253 chars). Neon-managed and internal hostnames are rejected.

maxLength 254 · minLength 3

entity_idstringrequired

The target entity's identifier within the branch. For `function` this is the function slug (which must already exist on the branch).

maxLength 255 · minLength 1

entity_typestringrequired

The kind of branch entity to point the domain at. v1 supports only `function`; any other value is rejected with `invalid_entity_type`.

maxLength 32 · minLength 1

Example request
{
  "domain": "string",
  "entity_id": "string",
  "entity_type": "function"
}

Responses

201The registered custom domainapplication/json
objectCustomDomain
binding_statusstring

Whether Neon's internal routing for the domain is published: `pending`, `present`, or `missing`. `missing` is an internal fault surfaced for support. Not an `enum`.

cname_targetstringrequired

The hostname the customer must point their custom domain at with a CNAME record. Empty when the serving region has no custom-domains front door configured. This is the activation input: point DNS here and the domain goes live (see `status`) once a certificate is issued on the first request.

dns_statusstring

The DNS + CAA portion of the check: `pending` (no records yet), `ok` (resolves to our edge and the CA is authorized), `misconfigured` (your CNAME does not resolve to our edge), or `caa_blocked` (your CAA records forbid Let's Encrypt). Not an `enum`.

domainstringrequired

The registered custom domain (normalized, lowercase).

entity_idstringrequired

The target entity's identifier within the branch. For `function` this is the function slug.

entity_typestringrequired

The kind of branch entity the domain targets. Possible values: `function` (v1 supports only `function`). Not an `enum`: new values may ship in later spec versions — treat any undocumented value as unknown.

statusstring

The domain's current validity, computed by a background check: `pending` (still converging — point your CNAME at `cname_target` and wait), `active` (live: DNS resolves to the edge, the CA is authorized, and routing is published), or `error` (a fixable problem — see `status_reason`). Not an `enum`: treat any undocumented value as unknown. May be absent briefly right after registration.

status_reasonstring

A short, stable machine-readable reason for a non-active `status` (e.g. `cname-not-pointing-at-edge`, `caa-blocks-lets-encrypt`, `binding-missing`), suitable for keying an actionable hint. Empty when active or pending.

Example response
{
  "binding_status": "string",
  "cname_target": "string",
  "dns_status": "string",
  "domain": "string",
  "entity_id": "string",
  "entity_type": "string",
  "status": "string",
  "status_reason": "string"
}
defaultGeneral Error. The request may or may not be safe to retry, depending on the HTTP method, response status code, and whether a response was received. - If no response is returned from the API, a network error or timeout likely occurred. - In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results. The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**. The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout. Any request that returns a `503 Service Unavailable` response is always safe to retry. Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress. application/json
objectGeneralError
codestringrequired

default ""

messagestringrequired

Error message

request_idstring

Unique identifier for the request, useful for debugging. You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.

Example response
{
  "code": "",
  "message": "string",
  "request_id": "string"
}
Documentation menu