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

Verify the domain

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

Checks both DNS records of the attached domain and, if they are correct, enables the domain: the application starts responding on it. The same call re-enables a domain that was disabled after a failed check.

Who can make the call — Access.

Parameters

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

The request body is empty.

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/domain/verify" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/domain/verify" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/domain/verify`,
  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const body = await res.json()
if (body.success) {
  console.log(`Domain enabled: ${body.data.domain.fqdn}`)
} else if (body.error.code === 'DOMAIN_VERIFICATION_FAILED') {
  // Show which record failed the check
  for (const record of body.error.details.records) {
    if (record.status !== 'ok') console.log(`${record.type} ${record.host}: ${record.status}`)
  }
} else {
  throw new Error(body.error.code)
}

JavaScript — OAuth application

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/domain/verify`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  }
)

Response fields

Field Type Description
Fieldsuccess Typeboolean Descriptiontrue when both records are correct and the domain is enabled
Fielddata.domain.id Typestring (UUID) DescriptionDomain attachment ID
Fielddata.domain.fqdn Typestring DescriptionDomain name in lowercase
Fielddata.domain.isApex Typeboolean Descriptiontrue — apex domain, false — subdomain
Fielddata.domain.status Typestring DescriptionDomain status, ACTIVE in this response. All values — Domain statuses
Fielddata.domain.source Typestring DescriptionOrigin of the domain. BYO — a domain you own
Fielddata.domain.dnsMode Typestring DescriptionWho maintains the DNS records. USER_DNS — you, at your DNS provider
Fielddata.domain.verifiedAt Typestring | null DescriptionTime of the last successful check, ISO 8601
Fielddata.domain.lastVerifiedAt Typestring | null DescriptionTime of the last check, successful or not, ISO 8601
Fielddata.domain.createdAt Typestring DescriptionTime the domain was attached, ISO 8601
Fielddata.domain.certIssued Typeboolean DescriptionWhether the certificate for https has been issued
Fielddata.records Typearray DescriptionResult for each record: TXT comes first, CNAME or A second
Fielddata.records[].type Typestring DescriptionRecord type: TXT, CNAME or A
Fielddata.records[].host Typestring DescriptionFull record name
Fielddata.records[].status Typestring Descriptionok — the record is correct, missing — not found, wrong — found with a different value. In this response both records are ok
Fielddata.records[].found Typestring[] DescriptionValues the check read from DNS. A CNAME record may carry IP addresses here: that is how a DNS provider that flattens CNAME into addresses responds

Response example

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

Error response example

422 — the TXT record is correct, but CNAME points to a different address:

JSON
{
  "success": false,
  "error": {
    "code": "DOMAIN_VERIFICATION_FAILED",
    "message": "Domain verification failed",
    "details": {
      "reason": "NOT_POINTING_TO_US",
      "records": [
        {
          "type": "TXT",
          "host": "_vibecode-challenge.app.example.com",
          "status": "ok",
          "found": [
            "vibe-verify=f36ac31f213d1e3630c75f000b6631f5"
          ]
        },
        {
          "type": "CNAME",
          "host": "app.example.com",
          "status": "wrong",
          "found": [
            "other.example.net"
          ]
        }
      ],
      "domain": {
        "id": "bea9db66-411b-432e-a365-283a74f5714f",
        "fqdn": "app.example.com",
        "isApex": false,
        "status": "FAILED",
        "source": "BYO",
        "dnsMode": "USER_DNS",
        "verifiedAt": null,
        "lastVerifiedAt": "2026-10-05T12:53:02.648Z",
        "createdAt": "2026-10-05T12:53:02.616Z",
        "certIssued": false
      },
      "hint": "Fix the records whose status is \"missing\" or \"wrong\" (see records), then repeat the check. A record that is already published is read from the authoritative name servers of the zone, so it is seen at once. If the check fails right after you edited DNS, the DNS provider has not published the change yet, or a resolver still returns the previous answer until the record TTL expires — for a name that did not exist before, that is the negative-cache TTL of the zone (SOA minimum, up to an hour). Repeating the check immediately returns the same result: wait a few minutes between attempts. The check is limited to 5 calls per minute."
    }
  }
}

The error.details fields of this refusal:

Field Type Description
Fielderror.details.reason Typestring DescriptionThe first record that failed. OWNERSHIP_TXT_MISSING — the TXT record is not found or incorrect, NOT_POINTING_TO_US — TXT is correct, but the domain does not point to the platform
Fielderror.details.records Typearray DescriptionResult for both records, with the same fields as data.records. Until the TXT record is confirmed, found is empty for both records
Fielderror.details.records[].hint Typestring DescriptionNot present on every record. DOUBLED_ZONE — the record is missing, but it was found under a name with the zone appended twice: host was entered in the DNS panel instead of name, see DNS records. HAS_AAAA — the domain name has an AAAA record, delete it
Fielderror.details.domain Typeobject DescriptionThe domain after the check, with the same fields as data.domain. Status — FAILED
Fielderror.details.hint Typestring DescriptionText in English: what to fix and when to repeat the check

Errors

HTTP Code Description
HTTP400 CodeFQDN_FORBIDDEN DescriptionBoth records are correct, but the domain name is not allowed: it must not contain bitrix. The domain moves to FAILED
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is not passed
HTTP401 CodeINVALID_API_KEY DescriptionThe key is not recognized: no such string exists on the platform
HTTP403 CodeINFRA_SCOPE_REQUIRED DescriptionThe key lacks the vibe:infra scope. Checked before the server lookup
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 — write operations are blocked for it
HTTP403 CodeCUSTOM_DOMAINS_DISABLED DescriptionCustom domains are not enabled for the server owner. Conditions — Access
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
HTTP404 CodeSERVER_NOT_FOUND DescriptionThe server is not found, is deleted, or is managed by another key
HTTP404 CodeNO_DOMAIN DescriptionNo domain is attached to the server. Checked before the access conditions that return 403
HTTP409 CodeSERVER_HAS_NO_APP_HOST DescriptionBoth records are correct, but the server has no public application address yet. The domain status does not change. Deploy the application and repeat the check
HTTP409 CodeDOMAIN_TAKEN_EXTERNAL DescriptionBoth records are correct, but after the domain was attached the name was connected to another Bitrix24 product. The domain moves to FAILED. Disconnect the name there and repeat the check
HTTP422 CodeDOMAIN_VERIFICATION_FAILED DescriptionA record is not found or incorrect. The domain moves to FAILED. Which record failed — in error.details.records
HTTP429 CodeRATE_LIMITED DescriptionThe limit of 5 requests per minute for this endpoint is exceeded. The limit is counted per key owner, not per individual key. The exact value is in the x-ratelimit-limit header (the cap is divided across replicas)
HTTP503 CodeCUSTOM_DOMAIN_REGISTRY_UNAVAILABLE DescriptionThe domain registry did not respond, or the platform could not read the address it compares the records against. The domain status stays as it was. Repeat the call later
HTTP503 Codeuser_self_deletion_pending DescriptionThe key owner requested deletion of their account on the portal. Access is restored once the deletion is cancelled

The full list of common API errors — Errors.

Known specifics

  • Repeating the check right after 422 returns the same result. A record the DNS provider has already published is read from the authoritative servers of the zone and is seen at once. If the refusal came right after a DNS edit, the provider has not published the change yet, or a caching DNS server still returns the previous answer until the record's time to live (TTL) expires. For a name that did not exist before, that is up to an hour. Wait a few minutes between attempts.
  • Checking a working domain can disable it. The call is also allowed for a domain in the ACTIVE status. If the records are incorrect by then, the domain moves to FAILED, and the application stops responding on it until the next successful check.
  • The certificate is issued after the response. When the domain reaches ACTIVE from another status, certIssued is false. https readiness is shown by GET /v1/infra/servers/:id/domain.

See also