---
title: "Re-apply DNS records with the stored Cloudflare grant"
method: POST
path: "/api/v1/sites/{slug}/custom-domains/connect/reapply-oauth"
tags: ["Domains"]
---

# Re-apply DNS records with the stored Cloudflare grant

`POST /api/v1/sites/{slug}/custom-domains/connect/reapply-oauth`

## Request

- Base URL: `https://api.dotsy.ai`
- URL: `https://api.dotsy.ai/api/v1/sites/{slug}/custom-domains/connect/reapply-oauth`
- Auth: HTTP bearer

Recovery without a browser: writes the routing and certificate-check records for the site's pending hosts again, using the Cloudflare grant the user already gave, then re-checks the hostnames. Use it when a connect stalled on stale or duplicate records. Needs a previous Cloudflare OAuth connect (`no_cloudflare_oauth_grant` otherwise). The body is ignored. Needs the site owner. Editors, viewers, guest tokens (`guest_requires_account`) and keys scoped to other sites are refused.

## Path parameters

- `slug` string, required

## Response `200`

Records re-applied.

- ReapplyCustomDomainOauthResponse
  - `applyResults` ConnectApplyResult[], required: What was written for each host.
    - `host` string, required
    - `routingOk` boolean, required
    - `routingCreated` number
    - `routingSkipped` number
    - `dcvOk` boolean
    - `dcvConflict` boolean: An existing TXT/CNAME record blocks the additive write (for example a stale certificate-check record).
    - `message` string
  - `connect` DomainConnect, required: What to do next to connect the pending hosts: the next action plus the connect session id.
    - `sessionId` string, required: The connect session. Pass it as `sessionId` to getCustomDomainConnect to resume.
    - `kind` 'oauth' | 'redirect' | 'widget' | 'manual' | 'wait' | 'done', required: What to do next. `oauth` / `redirect` / `widget`: open `openUrl` in a browser. `manual`: follow `instructions` and enter `records`. `wait`: nothing to do, DNS or the certificate is propagating — poll again. `done`: every host is connected.
    - `summary` string, required: One line to tell the user.
    - `openUrl` string: A URL to open in a browser (OAuth start, Domain Connect apply).
    - `openUrlLabel` string
    - `oauthLastError` string: Last Cloudflare OAuth error code (`access_denied`, `exchange_failed`, …) while still on the OAuth lane.
    - `instructions` string[]: Numbered steps when `kind` is `manual`.
    - `records` DnsRecord[]: Copy-paste DNS rows for the session's hosts. `host` says which host each row belongs to.
      - `type` string, required: DNS record type, e.g. `CNAME`, `TXT` or `A`.
      - `name` string, required: The record name to enter at the DNS provider (relative to the zone, e.g. `www` or `_acme-challenge.www`).
      - `value` string, required: The record value to enter.
      - `purpose` 'routing' | 'dcv' | 'apex', required: `routing`: points the hostname at Dotsy. `apex`: the same for a bare domain. `dcv`: proves you control the domain so the certificate can be issued.
      - `host` string: On `connect` records only: the session host this row belongs to.
      - `recordStatus` 'found' | 'missing' | 'mismatch' | 'waiting' | 'duplicate': A live DNS check of this record. Absent when no check has run. `duplicate` means extra TXT records at this name are blocking the certificate.
      - `nameError` 'doubled_suffix': The name looks like it was pasted as a full hostname and the provider appended the zone to it.
      - `useInstead` string: With `nameError`: the relative name to enter instead.
      - `dnsTxtCount` number: With `recordStatus: duplicate`: how many TXT answers exist at this name.
      - `dcvExpectedValues` string[]: Every certificate-check token that is currently acceptable at this name (Cloudflare rotated while pending).
    - `registrarDeepLink` string: A link to the DNS page at the detected provider.
    - `provider` object: The DNS provider detected from the domain's nameservers.
      - `id` string, required
      - `label` string, required
    - `nameServers` string[]: The domain's nameservers, when the provider was not recognised.
    - `providerApi` object: The paste-credentials lane (Name.com, GoDaddy): send the listed `fields` as `credentials` to connectCustomDomainProvider.
      - `fields` object[], required
        - `key` string, required
        - `label` string, required
        - `secret` boolean
        - `placeholder` string
      - `helpUrl` string, required
      - `helpLabel` string, required
      - `hasSavedCredentials` boolean, required
    - `entriAvailable` boolean, required
    - `lane` 'cloudflare_oauth' | 'domain_connect' | 'entri' | 'manual', required: How the DNS records get applied: `cloudflare_oauth` (Cloudflare DNS, with the user's grant), `domain_connect`, `entri`, or `manual` (the user pastes records at their provider).
    - `sessionStatus` 'in_progress' | 'partial' | 'complete', required
    - `hosts` object[], required
      - `host` string, required
      - `status` 'pending_dns' | 'pending_cert' | 'connected' | 'error', required: `pending_dns`: waiting for the DNS records. `pending_cert`: DNS is right, the HTTPS certificate is being issued. `connected`: live. `error`: Cloudflare could not set the hostname up (see `lastError`); it no longer holds a hostname slot.
      - `isPrimary` boolean, required
    - `canReapplyOauth` boolean: A stored Cloudflare OAuth grant exists, so reapplyCustomDomainOauth can fix the records without a browser.

## Other responses

- `400`: No stored Cloudflare grant for this account (`no_cloudflare_oauth_grant`).
- `401`: Missing or invalid credentials.
- `403`: Not allowed: only the site owner manages domains, and guest tokens cannot.
- `404`: No such site (`site_not_found`), or no pending external domains (`no_pending_domains`).
- `503`: Cloudflare OAuth is not configured on this server (`oauth_not_configured`).

---

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