For AI agents: markdown of this page — /docs-content-en/infra/domain/attach.md documentation index — /llms.txt

Attach a domain

POST /v1/infra/servers/:id/domain

Assigns your domain name to the application on the server and begins the first step of attachment: creating DNS records at the domain's DNS provider. The application starts accepting requests on the domain only after the records are verified successfully. A server can have only one domain.

Who can make the call — Access. The purpose of the records and the difference between host and name — DNS records.

Parameters

Parameter In Type Required Description
Parameterid Inpath Typestring (UUID) Requiredyes DescriptionServer ID. Source — the id field from the server list

Request fields (body)

Field Type Required Description
Fieldfqdn Typestring Requiredyes DescriptionDomain name without scheme, port or path, for example app.example.com. A subdomain or an apex domain is accepted. Case is ignored, leading and trailing spaces are trimmed. The name consists of at least two dot-separated labels; each label is 1 to 63 Latin letters, digits and hyphens, and a hyphen is not allowed at the start or the end of a label

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/domain" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fqdn": "app.example.com"
  }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/domain" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fqdn": "app.example.com"
  }'

JavaScript — personal key

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/domain`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      fqdn: 'app.example.com',
    }),
  }
)
const { data } = await res.json()
for (const record of data.instructions) {
  console.log(`${record.type} ${record.name} → ${record.value}`)
}

JavaScript — OAuth application

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/domain`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      fqdn: 'app.example.com',
    }),
  }
)

Response fields

Field Type Description
Fieldsuccess Typeboolean DescriptionAlways true on success
Fielddata.domain.id Typestring (UUID) DescriptionDomain attachment ID
Fielddata.domain.fqdn Typestring DescriptionThe attached name in lowercase
Fielddata.domain.isApex Typeboolean Descriptiontrue — the apex domain of the zone, false — a subdomain
Fielddata.domain.status Typestring DescriptionDomain status. After attachment — "PENDING_VERIFICATION". All values — Domain statuses
Fielddata.domain.source Typestring DescriptionOrigin of the domain. "BYO" — the domain is yours and was connected by you
Fielddata.domain.dnsMode Typestring DescriptionWho maintains the DNS records. "USER_DNS" — you, at your DNS provider
Fielddata.domain.verifiedAt Typestring (ISO 8601) | null DescriptionTime of the successful verification after which the domain became ACTIVE. After attachment — null
Fielddata.domain.lastVerifiedAt Typestring (ISO 8601) | null DescriptionTime of the last record verification, including a failed one. After attachment — null
Fielddata.domain.createdAt Typestring (ISO 8601) DescriptionTime of attachment
Fielddata.domain.certIssued Typeboolean DescriptionWhether the certificate for https has been issued. After attachment — false
Fielddata.instructions Typearray DescriptionTwo DNS records to create at the domain's DNS provider
Fielddata.instructions[].type Typestring DescriptionRecord type: "TXT", "CNAME" or "A"
Fielddata.instructions[].host Typestring DescriptionFull record name
Fielddata.instructions[].zone Typestring DescriptionZone in which the record is created
Fielddata.instructions[].name Typestring DescriptionRecord name relative to zone — the value entered in the "name" field of the DNS provider's panel. For the zone itself — "@"
Fielddata.instructions[].value Typestring DescriptionRecord value

Response example

Response 201 for attaching a subdomain:

JSON
{
  "success": true,
  "data": {
    "domain": {
      "id": "bea9db66-411b-432e-a365-283a74f5714f",
      "fqdn": "app.example.com",
      "isApex": false,
      "status": "PENDING_VERIFICATION",
      "source": "BYO",
      "dnsMode": "USER_DNS",
      "verifiedAt": null,
      "lastVerifiedAt": null,
      "createdAt": "2026-10-05T12:53:02.616Z",
      "certIssued": false
    },
    "instructions": [
      {
        "type": "TXT",
        "host": "_vibecode-challenge.app.example.com",
        "zone": "example.com",
        "name": "_vibecode-challenge.app",
        "value": "vibe-verify=f36ac31f213d1e3630c75f000b6631f5"
      },
      {
        "type": "CNAME",
        "host": "app.example.com",
        "zone": "example.com",
        "name": "app",
        "value": "lb.bitrix24.site"
      }
    ]
  }
}

The apex domain example.com would get "isApex": true, and the second record would be "type": "A" with "name": "@" and an IPv4 address in value. The rest of the response shape does not change.

Error response example

409 — the name is already attached to another server on the platform:

JSON
{
  "success": false,
  "error": {
    "code": "DOMAIN_TAKEN",
    "message": "This domain is already in use"
  }
}

Errors

HTTP Code Description
HTTP400 CodeINVALID_REQUEST DescriptionThe fqdn field is missing or is not a domain name
HTTP400 CodeFQDN_INVALID DescriptionAn IP address was passed in fqdn
HTTP400 CodeFQDN_RESERVED DescriptionThe name belongs to the platform: it is the platform's domain or its subdomain
HTTP400 CodeFQDN_FORBIDDEN DescriptionThe name is forbidden: it contains the substring bitrix
HTTP400 CodeINVALID_JSON_BODY DescriptionThe request body cannot be parsed as JSON
HTTP409 CodeCUSTOM_DOMAIN_GALAXY_MOVE_ACTIVE DescriptionThe server is moving to a Galaxy: it is the old server of the move or the place prepared for it. Attach the domain after the move is completed or cancelled
HTTP409 CodeCUSTOM_DOMAIN_LIMIT DescriptionThe server already has a domain, including one with the same name. Detach it first
HTTP409 CodeDOMAIN_TAKEN DescriptionThe name is attached to another server on the platform
HTTP409 CodeDOMAIN_TAKEN_EXTERNAL DescriptionThe name is connected to another Bitrix24 product. Disconnect it there and repeat the call
HTTP503 CodeCUSTOM_DOMAIN_REGISTRY_UNAVAILABLE DescriptionThe domain registry did not respond. The domain is not attached; repeat the call later
HTTP403 CodeCUSTOM_DOMAINS_DISABLED DescriptionCustom domains are not enabled for the server owner
HTTP403 CodeCUSTOM_DOMAINS_ZONE_UNSUPPORTED DescriptionThe region of the Bitrix24 account does not support custom domains
HTTP403 CodeCUSTOM_DOMAINS_REQUIRE_COMMERCIAL DescriptionThe Bitrix24 account has no commercial plan
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is missing
HTTP401 CodeINVALID_API_KEY DescriptionThe key is not recognized — no such key exists on the platform
HTTP403 CodeINFRA_SCOPE_REQUIRED DescriptionThe key lacks the vibe:infra scope
HTTP403 CodeINFRA_FORBIDDEN_FOR_COWORK_KEY DescriptionThe call was made with a Cowork/Code key — such a key works with data only and cannot perform write operations. What to do — Project key for deploy
HTTP403 CodeWRITE_BLOCKED_READONLY_KEY DescriptionThe key is in read-only mode and cannot perform write operations
HTTP404 CodeSERVER_NOT_FOUND DescriptionNo server with this id exists, or it is managed by a key other than the one used for the call
HTTP429 CodeRATE_LIMITED DescriptionThe limit of 5 requests per minute for this endpoint was exceeded. The limit is counted per key owner, not per individual key. The exact value arrives in the x-ratelimit-limit header (the cap is divided across replicas)
HTTP503 Codeuser_self_deletion_pending DescriptionThe key owner requested deletion of their account on the portal. Access is restored once the deletion is cancelled

Full list of common API errors — Errors.

Known specifics

  • Order of checks. The key scope and server ownership are checked first, then the three access conditions for custom domains, and only after them the request body. So a request with an invalid fqdn from an account that has no access to custom domains gets 403, not 400. The exception is INVALID_JSON_BODY: the body is parsed before the key check, so a body with a JSON syntax error gets 400 before all other refusals. The FQDN_FORBIDDEN and DOMAIN_TAKEN_EXTERNAL refusals come last: they are issued by the domain registry, which the platform queries after its own checks.
  • The name is fully secured only at verification. Attachment closes the name to other servers on the platform, but in the Bitrix24 domain registry it is taken only after a successful verification. If the name is connected to another Bitrix24 product between attachment and verification, the verification returns the DOMAIN_TAKEN_EXTERNAL refusal instead.
  • The records can be fetched again. The instructions array with the same TXT value is returned at any time by GET /v1/infra/servers/:id/domain; storing the attachment response is not required.

See also