---
title: "Remove a domain, removing or keeping the DNS records we added"
method: DELETE
path: "/connections/{id}"
tags: ["Connections"]
---

# Remove a domain, removing or keeping the DNS records we added

`DELETE /connections/{id}`

## Request

- Base URL: `https://api.customdomain.ai/v1`
- URL: `https://api.customdomain.ai/v1/connections/{id}`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.customdomain.ai/oauth/agent/authorize`, token URL `https://api.customdomain.ai/oauth/agent/token`, scopes: `domains:disconnect`)

Removes the domain, and with `records` says what happens to the DNS records we added. `remove` deletes them and puts back what they replaced, when we know it; `keep` leaves them. What `remove` can do depends on how the domain was connected, and `GET /connections/{id}/removal` says so before you call this: with access we kept (our hosted zone, a kept sign-in, a continuous provider account, a kept Domain Connect authorization) it is automatic; with a one time sign-in or key it needs one more authorization, and this answers `409 reauthorization_required` with the plan (sign in again with `oauth:start` and `purpose: "remove"`, send a key to `POST /connections/{id}:disconnect`, or call this with `records=keep` and follow the manual steps); for Domain Connect one-click and manual setups the answer lists the exact manual steps. Records whose value changed since we wrote them, values that were already there before we wrote them, and records another connected domain still uses are never touched. With a key or a sign-in, the zone must show at least one of our records before any record is reported removed or gone; otherwise the answer lists the manual steps (the key may belong to another account).

Whatever the choice, the domain stops being served the moment the removal starts (edges forget it within a minute), its certificate stops renewing and is deleted, its monitoring stops, and `connection.disconnected` carries a `removal` object with what happened to the records. `GET /connections/{id}/removal` answers the same outcome once the connection is gone. A second removal of the same domain while one runs answers `409 removal_in_progress`.

Without `records` the call keeps its original contract: records are taken out only where it always took them out (a kept Domain Connect authorization, a kept sign-in, our hosted zone) and kept otherwise, including with a connected provider account or the Route 53 access role; the answer is `204` with no body. With `records` the answer is `200` with the outcome.

An end user's widget token (scope `connect`) must be bound to the domain and, when the connection names an end user, minted with that `end_user_ref`; otherwise `403`.

A delegated agent token needs `domains:disconnect`, a scope of its own because the removal takes the domain offline, and must send `confirm` naming the domain. Without it the answer is `400 confirmation_required`, and with another domain `409 confirmation_mismatch`; nothing is removed either way. Another application's connection answers `404`.

## Path parameters

- `id` string, required

## Query parameters

- `records` 'remove' | 'keep'
- `confirm` string

## Response `200`

Removed; what happened to the records

- DisconnectResult
  - `connection_id` string, required
  - `domain` string, required
  - `disconnected` boolean, required
  - `records` RemovalOutcome, required
    - `choice` 'remove' | 'keep', required
    - `outcome` 'removed' | 'partly_removed' | 'kept' | 'manual' | 'in_use' | 'not_needed' | 'failed', required
    - `via` string
    - `removed` RemovalResult[]
      - `type` string, required
      - `name` string, required
      - `value` string, required
      - `note` string
    - `restored` RemovalResult[]
      - `type` string, required
      - `name` string, required
      - `value` string, required
      - `note` string
    - `left_in_place` RemovalResult[]
      - `type` string, required
      - `name` string, required
      - `value` string, required
      - `note` string
    - `failed` RemovalResult[]
      - `type` string, required
      - `name` string, required
      - `value` string, required
      - `note` string
    - `manual_steps` string[]
  - `serving` 'stopped', required
  - `certificate` 'removed' | 'kept' | 'none', required
  - `monitoring` 'stopped', required

## Other responses

- `204`: Removed (no records choice given): records taken out only through a kept Domain Connect authorization, a kept sign-in or our hosted zone, kept otherwise
- `400`: `confirmation_required`: a delegated agent token did not send `confirm`; `details` names the domain to send. `invalid_request`: `records` is neither `remove` nor `keep`. Nothing was removed.
- `401`: Error envelope: {code, title, details}.
- `403`: Error envelope: {code, title, details}.
- `404`: Error envelope: {code, title, details}.
- `409`: `reauthorization_required`: removing the records needs one more sign-in or key; `plan` is the removal plan. `removal_in_progress`: another removal of the domain is running. `confirmation_mismatch`: a delegated agent token's `confirm` names another domain. Nothing was changed.

---

[API](https://skmtc.dev/customdomain/apis/customdomain-control-plane-api.md) · [All operations](https://skmtc.dev/customdomain/apis/customdomain-control-plane-api/llms.txt) · [OpenAPI document](https://skmtc.dev/customdomain/apis/customdomain-control-plane-api/revisions/34d89cb7a7cd?raw)
