---
title: "Organization endpoints — API reference | Data Tactical Group"
route: "/docs/api/reference/organization"
updated: "2026-10-23"
---

# Organization

16 endpoints, generated from the API's own OpenAPI document. Organizations a person can find or join, verified domains and join requests.

## PATCH `/v2/account/organization`

**Rename the active organization**

Credentials: API key or App session. Operation id `acctRenameOrganization`.

Either credential (an API key or a session); resolves the caller's active organization (`X-DTG-Org`). Owner or admin. T18: a name must be unique among the organizations that have verified the same domain (compared trimmed, whitespace-collapsed and case-folded); names are not globally unique.

### Parameters

**`X-DTG-Org` header · string (uuid)**

The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

### Request body

Required; `application/json`.

**`name` string required**

A non-blank string of at most 120 characters, stored trimmed. Must be unique among the organizations that have verified the same domain. (at most 120 characters)

### Responses

#### `200` success

The organization's id and new name.

As `application/json`.

**`id` string (uuid) always present**

The organization's id.

**`name` string always present**

The name as stored (trimmed).

#### `400` error

Bad Request. Codes: [`bad_request`](/docs/api/errors#code-bad-request) (`name` is not a non-blank string of at most 120 characters), [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON, or uses an unsupported content encoding).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership) (the account has no active membership in an active organization), [`account_suspended`](/docs/api/errors#code-account-suspended) (O56: the signed-in person's own account is suspended by DTG; `reason` where recorded), [`org_suspended`](/docs/api/errors#code-org-suspended) (the selected organization is suspended by DTG; the body carries `organization {id, name}` and `reason`), [`org_closed`](/docs/api/errors#code-org-closed) (the selected organization is closed; the body carries `organization {id, name}`), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries `expected` and `base_url`, the address that serves it), [`role_required`](/docs/api/errors#code-role-required) (the caller's role is not one of those named; the body carries `required`). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (the `X-DTG-Org` header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As `application/problem+json`.

#### `409` error

Conflict. Codes: [`org_name_taken`](/docs/api/errors#code-org-name-taken) (another organization at one of this organization's verified domains already carries the name; the body carries `name`, `domain` and `auto_named`).

As `application/problem+json`.

#### `413` error

Payload Too Large. Codes: [`body_too_large`](/docs/api/errors#code-body-too-large) (the body is over this endpoint's 16 KB limit; the body carries `limit_bytes`).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`bad_request`](/docs/api/errors#code-bad-request) (400), [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`role_required`](/docs/api/errors#code-role-required) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`org_name_taken`](/docs/api/errors#code-org-name-taken) (409), [`body_too_large`](/docs/api/errors#code-body-too-large) (413), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/account/organization/close`

**The terms of closing the active organization**

Credentials: API key or App session. Operation id `acctPreviewOrganizationClose`.

Either credential (an API key or a session); resolves the caller's active organization (`X-DTG-Org`). Owner only. D57: states what a close does (members removed, the subscription cancelled with NO refund, all data kept) before the click. No side effects.

### Parameters

**`X-DTG-Org` header · string (uuid)**

The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

### Responses

#### `200` success

The terms.

As `application/json`.

**`org` object always present**

The organization.

**`org.id` string (uuid) always present**

Its id.

**`org.name` string always present**

Its name.

**`org.status` "active" | "suspended" | "closed" always present**

Its status (always `active` for a caller here).

**`members_to_remove` integer always present**

Active memberships the close ends (the owner's included).

**`subscription` object always present**

The subscription.

**`subscription.active` boolean always present**

True when there is a subscription that the close cancels at once.

**`subscription.plan` string or null always present**

Its plan code; null when there is no live subscription.

**`refund` "none" always present**

Always `none`: closing cancels with no refund.

**`data_retention` "kept" always present**

Always `kept`: nothing is deleted; the former owner can reopen it (`POST /v2/reopen/{id}`).

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership) (the account has no active membership in an active organization), [`account_suspended`](/docs/api/errors#code-account-suspended) (O56: the signed-in person's own account is suspended by DTG; `reason` where recorded), [`org_suspended`](/docs/api/errors#code-org-suspended) (the selected organization is suspended by DTG; the body carries `organization {id, name}` and `reason`), [`org_closed`](/docs/api/errors#code-org-closed) (the selected organization is closed; the body carries `organization {id, name}`), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries `expected` and `base_url`, the address that serves it), [`role_required`](/docs/api/errors#code-role-required) (the caller's role is not one of those named; the body carries `required`).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (the `X-DTG-Org` header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`role_required`](/docs/api/errors#code-role-required) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## POST `/v2/account/organization/close`

**Close the active organization**

Credentials: API key or App session. Operation id `acctCloseOrganization`.

Either credential (an API key or a session); resolves the caller's active organization (`X-DTG-Org`). Owner only. Takes no body. D57: the subscription is cancelled at once with no refund (D50; if the payment gateway refuses, nothing is closed); every membership ends (seats freed, keys revoked) but no session ends (T27: a person's other organizations keep working); status becomes `closed`; any remembered `last_org_id` pointing at it is cleared; an `org.closed` audit row is written. All data is kept and the former owner can reopen it (`POST /v2/reopen/{id}`).

### Parameters

**`X-DTG-Org` header · string (uuid)**

The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

### Responses

#### `200` success

What the close did.

As `application/json`.

**`org_id` string (uuid) always present**

The closed organization's id.

**`memberships_removed` integer always present**

Memberships ended (seats freed, keys revoked).

**`subscription_cancelled` boolean always present**

True when a live subscription was cancelled (no refund).

#### `400` error

Bad Request. Codes: [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON, or uses an unsupported content encoding).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership) (the account has no active membership in an active organization), [`account_suspended`](/docs/api/errors#code-account-suspended) (O56: the signed-in person's own account is suspended by DTG; `reason` where recorded), [`org_suspended`](/docs/api/errors#code-org-suspended) (the selected organization is suspended by DTG; the body carries `organization {id, name}` and `reason`), [`org_closed`](/docs/api/errors#code-org-closed) (the selected organization is closed; the body carries `organization {id, name}`), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries `expected` and `base_url`, the address that serves it), [`role_required`](/docs/api/errors#code-role-required) (the caller's role is not one of those named; the body carries `required`). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (the `X-DTG-Org` header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As `application/problem+json`.

#### `413` error

Payload Too Large. Codes: [`body_too_large`](/docs/api/errors#code-body-too-large) (the body is over this endpoint's 16 KB limit; the body carries `limit_bytes`).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

#### `500` error

Internal Server Error. Codes: [`internal_error`](/docs/api/errors#code-internal-error) (the payment gateway failed to cancel the subscription; nothing was closed; retry).

As `application/problem+json`.

Problem codes: [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`role_required`](/docs/api/errors#code-role-required) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`body_too_large`](/docs/api/errors#code-body-too-large) (413), [`rate_limited`](/docs/api/errors#code-rate-limited) (429), [`internal_error`](/docs/api/errors#code-internal-error) (500). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/account/audit`

**The organization's audit trail**

Credentials: API key or App session. Operation id `acctListAudit`.

Either credential (an API key or a session); resolves the caller's active organization (`X-DTG-Org`). Owner or admin. L17/D60: what was done to the organization, newest first, within the 24-month window. JSON: at most 200 rows. With `Accept: text/csv`: the whole window as a file (the same as `GET /v2/account/audit.csv`), recorded as a CSV usage event that costs no points and does not count anyone as active. T108: a `member` that is not an id is 400 [`invalid_field`](/docs/api/errors#code-invalid-field) (it answered 500).

### Parameters

**`X-DTG-Org` header · string (uuid)**

The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

**`action` query · string**

An action prefix: `cluster.` matches every cluster action, `billing.changed` one action. The values are listed by `GET /v2/account/audit/actions`.

**`member` query · string (uuid)**

Only rows whose actor is this account id (a uuid).

### Responses

#### `200` success

The trail.

As `application/json`, `text/csv`.

**`data` array of AcctAuditRow always present**

At most 200 rows inside the retention window.

**`data[].id` string (uuid) always present**

The row id.

**`data[].ts` string (date-time) always present**

When it happened.

**`data[].action` string always present**

The action (for example `key.created`); `GET /v2/account/audit/actions` lists every one with its label.

**`data[].group` string always present**

The group the row belongs to (the filter chips): `Sign-ins`, `Members`, `Counties`, `Clusters`, `Billing`, `Keys`, `Policy`, `Organization`, and `DTG` in DTG's own organization only.

**`data[].summary` string always present**

One sentence describing the row, rendered when read. The actor is not in it.

**`data[].actor_via` "session" | "api\_key" | "admin" | "system" always present**

How the actor acted: `session`, `api_key`, `admin` (DTG staff; never named on a customer's trail) or `system` (a job).

**`data[].actor` object or null always present**

Who acted; null for DTG staff and system rows.

**`data[].actor.id` string (uuid) always present**

The actor's account id.

**`data[].actor.email` string or null always present**

Their address; a closed account shows a `closed+<id>@invalid` tombstone, and null when the account row is gone.

**`data[].actor.display_name` string or null always present**

Their display name; null when none or closed.

**`data[].target_type` string or null always present**

What was acted on (for example `api_key`, `organization`, `account`).

**`data[].target_id` string or null always present**

The target's id, as text.

**`data[].detail` object always present**

The structured facts of the row (never a secret).

**`retention_months` integer always present**

How far back the trail reaches, in months (24).

#### `400` error

Bad Request. Codes: [`bad_request`](/docs/api/errors#code-bad-request) (`action` or `member` given more than once), [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON, or uses an unsupported content encoding).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership) (the account has no active membership in an active organization), [`account_suspended`](/docs/api/errors#code-account-suspended) (O56: the signed-in person's own account is suspended by DTG; `reason` where recorded), [`org_suspended`](/docs/api/errors#code-org-suspended) (the selected organization is suspended by DTG; the body carries `organization {id, name}` and `reason`), [`org_closed`](/docs/api/errors#code-org-closed) (the selected organization is closed; the body carries `organization {id, name}`), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries `expected` and `base_url`, the address that serves it), [`role_required`](/docs/api/errors#code-role-required) (the caller's role is not one of those named; the body carries `required`).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (the `X-DTG-Org` header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`bad_request`](/docs/api/errors#code-bad-request) (400), [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`role_required`](/docs/api/errors#code-role-required) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/account/audit.csv`

**Download the audit trail as CSV**

Credentials: API key or App session. Operation id `acctDownloadAudit`.

Either credential (an API key or a session); resolves the caller's active organization (`X-DTG-Org`). Owner or admin. The suffix form of `Accept: text/csv` on `GET /v2/account/audit`: the whole 24-month window, same filters. Recorded as a CSV usage event that costs no points and does not count anyone as active.

### Parameters

**`X-DTG-Org` header · string (uuid)**

The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

**`action` query · string**

An action prefix: `cluster.` matches every cluster action, `billing.changed` one action. The values are listed by `GET /v2/account/audit/actions`.

**`member` query · string (uuid)**

Only rows whose actor is this account id (a uuid).

### Responses

#### `200` success

The trail as CSV.

As `text/csv`.

#### `400` error

Bad Request. Codes: [`bad_request`](/docs/api/errors#code-bad-request) (`action` or `member` given more than once), [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON, or uses an unsupported content encoding).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership) (the account has no active membership in an active organization), [`account_suspended`](/docs/api/errors#code-account-suspended) (O56: the signed-in person's own account is suspended by DTG; `reason` where recorded), [`org_suspended`](/docs/api/errors#code-org-suspended) (the selected organization is suspended by DTG; the body carries `organization {id, name}` and `reason`), [`org_closed`](/docs/api/errors#code-org-closed) (the selected organization is closed; the body carries `organization {id, name}`), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries `expected` and `base_url`, the address that serves it), [`role_required`](/docs/api/errors#code-role-required) (the caller's role is not one of those named; the body carries `required`).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (the `X-DTG-Org` header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`bad_request`](/docs/api/errors#code-bad-request) (400), [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`role_required`](/docs/api/errors#code-role-required) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/account/audit/actions`

**The audit trail's action vocabulary**

Credentials: API key or App session. Operation id `acctListAuditActions`.

Either credential (an API key or a session); resolves the caller's active organization (`X-DTG-Org`). Owner or admin. T37: every action the trail can carry, with a short label, under its group. The `DTG` group is listed only in DTG's own organization. No side effects.

### Parameters

**`X-DTG-Org` header · string (uuid)**

The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

### Responses

#### `200` success

The vocabulary.

As `application/json`.

**`data` array of object always present**

The groups.

**`data[].group` string always present**

The group name (as on the rows).

**`data[].actions` array of object always present**

Its actions.

**`data[].actions[].action` string always present**

The action, the value `?action=` filters on.

**`data[].actions[].label` string always present**

A short label for it.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership) (the account has no active membership in an active organization), [`account_suspended`](/docs/api/errors#code-account-suspended) (O56: the signed-in person's own account is suspended by DTG; `reason` where recorded), [`org_suspended`](/docs/api/errors#code-org-suspended) (the selected organization is suspended by DTG; the body carries `organization {id, name}` and `reason`), [`org_closed`](/docs/api/errors#code-org-closed) (the selected organization is closed; the body carries `organization {id, name}`), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries `expected` and `base_url`, the address that serves it), [`role_required`](/docs/api/errors#code-role-required) (the caller's role is not one of those named; the body carries `required`).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (the `X-DTG-Org` header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`role_required`](/docs/api/errors#code-role-required) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/reopen`

**Closed organizations this person may reopen**

Credentials: API key or App session. Operation id `acctListReopenable`.

Account-only: it authenticates the person (an API key or a session) and resolves NO organization, so `X-DTG-Org` is ignored and it answers a person with no active membership at all, or whose only organization is suspended or closed. It does not apply the live/sandbox instance check. D57: the closed organizations this person was an owner of. Works with no active organization at all.

### Responses

#### `200` success

The closed organizations.

As `application/json`.

**`data` array of object always present**

Newest close first.

**`data[].id` string (uuid) always present**

The organization's id (the `{id}` to reopen).

**`data[].name` string always present**

Its name.

**`data[].closed_at` string (date-time) or null always present**

When it closed.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential; no organization bucket on an account-only route), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## POST `/v2/reopen/{id}`

**Reopen a closed organization**

Credentials: API key or App session. Operation id `acctReopenOrganization`.

Account-only: it authenticates the person (an API key or a session) and resolves NO organization, so `X-DTG-Org` is ignored and it answers a person with no active membership at all, or whose only organization is suspended or closed. It does not apply the live/sandbox instance check. Former owner only. Takes no body. D57: the organization becomes active with all its data; ONLY the reopener's membership comes back (as a seated owner); other former members must be invited again. The cancelled subscription is not restored: start billing again. Writes an `org.reopened` audit row.

### Parameters

**`id` path · string (uuid) required**

The closed organization's id.

### Responses

#### `200` success

The reopened organization.

As `application/json`.

**`org_id` string (uuid) always present**

The organization's id.

**`membership_id` string (uuid) always present**

The reopener's membership, active again as a seated owner.

#### `400` error

Bad Request. Codes: [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON, or uses an unsupported content encoding).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`key_revoked`](/docs/api/errors#code-key-revoked) (the API key was revoked; `revoked_at`, `reason`, and a sentence saying when and why); [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As `application/problem+json`.

#### `403` error

Forbidden. [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (a sandbox key may write only clusters), and the authentication middleware's [`no_membership`](/docs/api/errors#code-no-membership), [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended), [`org_closed`](/docs/api/errors#code-org-closed), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (`base_url` names the address that serves the key).

As `application/problem+json`.

#### `404` error

Not Found. Codes: [`not_found`](/docs/api/errors#code-not-found) (no such organization, the id is not a uuid, or the caller was never its owner; indistinguishable on purpose).

As `application/problem+json`.

#### `409` error

Conflict. Codes: [`not_closed`](/docs/api/errors#code-not-closed) (the organization is not closed; the body carries `status`).

As `application/problem+json`.

#### `413` error

Payload Too Large. Codes: [`body_too_large`](/docs/api/errors#code-body-too-large) (the body is over this endpoint's 4 KB limit; the body carries `limit_bytes`).

As `application/problem+json`.

#### `429` error

Only the per-minute rate limit: [`rate_limited`](/docs/api/errors#code-rate-limited) (120 requests a minute per credential; no organization bucket on an account-only route), with `Retry-After` and `X-RateLimit-*`.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`not_closed`](/docs/api/errors#code-not-closed) (409), [`body_too_large`](/docs/api/errors#code-body-too-large) (413), [`rate_limited`](/docs/api/errors#code-rate-limited) (429). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/account/domains`

**The organization's domain claims and their verification state**

Credentials: API key or App session. Operation id `orgListDomains`.

The owner or an admin (O63 S11, Q22; 403 [`role_required`](/docs/api/errors#code-role-required) for anyone else); `default_role: admin` is an owner's to set, and never on DTG's organization (AUTH-8). Domain claims are not exclusive: several organizations may claim and verify the same domain. A verified claim lists the organization for people at that domain (`GET /v2/orgs/discover`), lets them join by its `join_policy`, and lets an admin at the domain claim ownership. A pending claim grants nothing; its `verify_token` is the TXT value to publish.

### Responses

#### `200` success

The claims.

As `application/json`.

**`data` array of OrgDomainClaim always present**

Every claim of the organization, oldest first.

**`data[].id` string (uuid) always present**

The claim's id.

**`data[].domain` string always present**

The claimed domain, lower case.

**`data[].verified_at` string (date-time) or null always present**

When the claim was verified; null while pending. Only a verified claim lets people at the domain discover and join, and lets an admin claim ownership.

**`data[].verify_method` "owner\_email" | "dns\_txt" | null always present**

How it was verified: `owner_email` (an owner's verified sign-in address is at the domain; immediate) or `dns_txt` (a TXT record). Null while pending.

**`data[].join_policy` "off" | "request" | "auto" always present**

What people at the domain may do once it is verified: `off` (not discoverable), `request` (ask to join; an owner or admin approves), `auto` (join at once).

**`data[].default_role` "member" | "admin" always present**

The role a person joining through this domain receives.

**`data[].created_at` string (date-time) always present**

When the claim was made.

**`data[].verify_token` string or null always present**

While pending, the value to publish as a TXT record `dtg-verify=<verify_token>` at the domain; null once verified.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`no_membership`](/docs/api/errors#code-no-membership), [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended), [`org_closed`](/docs/api/errors#code-org-closed), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (see `GET /v2/account/members`; `base_url` names the address that serves the key).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (`X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`not_found`](/docs/api/errors#code-not-found) (404). Every problem is a [problem document](/docs/api/errors).

## POST `/v2/account/domains`

**Claim a domain (verified at once by an owner's address, else by DNS TXT)**

Credentials: API key or App session. Operation id `orgClaimDomain`.

Owner or admin. Domains of public email providers are refused. Two ways to verify:

- Owner email: if an owner of the organization has a verified sign-in address at the domain, the claim is verified at once (`verify_method: owner_email`).
- DNS TXT: otherwise the claim is pending; publish a TXT record `dtg-verify=<verify_token>` at the domain and call `POST /v2/account/domains/{id}/verify`.

The name rule: an organization's name must be unique among the active organizations that have verified the same domain (compared trimmed, with whitespace collapsed and case ignored). A claim that would verify at once is refused 409 [`org_name_taken`](/docs/api/errors#code-org-name-taken) if another organization that verified the domain already carries this organization's name, and nothing is written. A pending claim is accepted, and its `warnings` names the refusal its verification would meet. Claiming a domain this organization already claimed updates only `join_policy` and `default_role` (the verification state is left as it was) and still answers 201. Writes a `domain.claimed` audit row.

### Request body

Required; `application/json`.

**`domain` string required**

The domain to claim (trimmed, lower-cased; a public email provider is refused).

**`join_policy` "off" | "request" | "auto"**

The join policy (see `OrgDomainClaim.join_policy`). (default "request")

**`default_role` "member" | "admin"**

The role a joiner through this domain receives. (default "member")

### Responses

#### `201` success

The claim.

As `application/json`.

**`id` string (uuid) always present**

The claim's id.

**`domain` string always present**

The claimed domain.

**`verified_at` string (date-time) or null always present**

Set when the claim verified at once (`owner_email`); null when pending.

**`verify_method` "owner\_email" | null always present**

`owner_email` when verified at once; null when pending (verify with a TXT record).

**`join_policy` "off" | "request" | "auto" always present**

The join policy as stored.

**`default_role` "member" | "admin" always present**

The default role as stored.

**`warnings` array of OrgNameTakenWarning always present**

Empty unless the claim is pending and its verification would be refused for the name rule.

**`warnings[].code` "org\_name\_taken" always present**

Always [`org_name_taken`](/docs/api/errors#code-org-name-taken).

**`warnings[].name` string always present**

The organization's current name, which another organization that has verified this domain already carries.

**`warnings[].domain` string always present**

The domain the collision is at.

**`warnings[].auto_named` boolean always present**

True when the name is still the default derived from the creator's email domain; ask for a chosen name.

**`warnings[].detail` string always present**

A sentence for people explaining the collision and that verifying will be refused until the organization is renamed.

**`verify_token` string**

Present only while pending. Publish `dtg-verify=<verify_token>` as a TXT record at the domain.

**`dns_instructions` string**

Present only while pending. The same instruction as a sentence, naming the verify route.

#### `400` error

Bad request. Codes: [`bad_request`](/docs/api/errors#code-bad-request) (`domain` missing or not a valid domain name; `join_policy` or `default_role` not an allowed value), [`public_email_domain`](/docs/api/errors#code-public-email-domain) (a public email provider's domain; `domain`; `errors` repeats it), [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`role_required`](/docs/api/errors#code-role-required) (the caller is a member; carries `required`), [`no_membership`](/docs/api/errors#code-no-membership), [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended), [`org_closed`](/docs/api/errors#code-org-closed), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (see `GET /v2/account/members`; `base_url` names the address that serves the key). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (`X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `409` error

Conflict. Codes: [`org_name_taken`](/docs/api/errors#code-org-name-taken) (the claim would verify at once and another organization that verified this domain already carries this organization's name; carries `name`, `domain`, `auto_named`; rename the organization, then claim).

As `application/problem+json`.

#### `413` error

Payload too large. Codes: [`body_too_large`](/docs/api/errors#code-body-too-large) (over 8 KB; carries `limit_bytes`).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`bad_request`](/docs/api/errors#code-bad-request) (400), [`public_email_domain`](/docs/api/errors#code-public-email-domain) (400), [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`role_required`](/docs/api/errors#code-role-required) (403), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`org_name_taken`](/docs/api/errors#code-org-name-taken) (409), [`body_too_large`](/docs/api/errors#code-body-too-large) (413). Every problem is a [problem document](/docs/api/errors).

## PATCH `/v2/account/domains/{id}`

**Change a claim's join policy or default role**

Credentials: API key or App session. Operation id `orgUpdateDomain`.

Owner or admin. Changes what people at the domain may do (`join_policy`) and the role they receive (`default_role`). Applies to joins from now on; existing members are unchanged. Works on a pending claim too. Writes a `domain.updated` audit row.

### Parameters

**`id` path · string (uuid) required**

The domain claim's id. A value that is not a UUID answers 404.

### Request body

Required; `application/json`.

**`join_policy` "off" | "request" | "auto"**

The new join policy.

**`default_role` "member" | "admin"**

The new default role for joiners.

### Responses

#### `200` success

The claim after the change.

As `application/json`.

**`id` string (uuid) always present**

The claim's id.

**`domain` string always present**

The domain.

**`verified_at` string (date-time) or null always present**

When verified; null while pending.

**`verify_method` "owner\_email" | "dns\_txt" | null always present**

How it was verified; null while pending.

**`join_policy` "off" | "request" | "auto" always present**

The join policy.

**`default_role` "member" | "admin" always present**

The default role for joiners.

#### `400` error

Bad request. Codes: [`bad_request`](/docs/api/errors#code-bad-request) (`join_policy` or `default_role` not an allowed value, or nothing to update), [`malformed_json`](/docs/api/errors#code-malformed-json) (the body is not valid JSON).

As `application/problem+json`.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`role_required`](/docs/api/errors#code-role-required) (the caller is a member; carries `required`), [`no_membership`](/docs/api/errors#code-no-membership), [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended), [`org_closed`](/docs/api/errors#code-org-closed), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (see `GET /v2/account/members`; `base_url` names the address that serves the key). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (no claim with that id in this organization, or `X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `413` error

Payload too large. Codes: [`body_too_large`](/docs/api/errors#code-body-too-large) (over 8 KB; carries `limit_bytes`).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`bad_request`](/docs/api/errors#code-bad-request) (400), [`malformed_json`](/docs/api/errors#code-malformed-json) (400), [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`role_required`](/docs/api/errors#code-role-required) (403), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`body_too_large`](/docs/api/errors#code-body-too-large) (413). Every problem is a [problem document](/docs/api/errors).

## DELETE `/v2/account/domains/{id}`

**Remove a domain claim**

Credentials: API key or App session. Operation id `orgDeleteDomain`.

Owner or admin. Deletes the claim: the organization stops being listed for that domain and people there can no longer join through it. Members who joined through it stay members. Writes a `domain.removed` audit row.

### Parameters

**`id` path · string (uuid) required**

The domain claim's id. A value that is not a UUID answers 404.

### Responses

#### `204` success

Removed. No body.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`role_required`](/docs/api/errors#code-role-required) (the caller is a member; carries `required`), [`no_membership`](/docs/api/errors#code-no-membership), [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended), [`org_closed`](/docs/api/errors#code-org-closed), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (see `GET /v2/account/members`; `base_url` names the address that serves the key). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (no claim with that id in this organization, or `X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`role_required`](/docs/api/errors#code-role-required) (403), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404). Every problem is a [problem document](/docs/api/errors).

## POST `/v2/account/domains/{id}/verify`

**Verify a pending claim by its DNS TXT record**

Credentials: API key or App session. Operation id `orgVerifyDomain`.

Owner or admin. Looks up the TXT records at the domain and verifies the claim when one reads `dtg-verify=<verify_token>` (DNS changes can take time to appear; retry after a 409 [`dns_txt_not_found`](/docs/api/errors#code-dns-txt-not-found) ). Before verifying, the name rule is checked (see `POST /v2/account/domains`): if another organization that verified the domain already carries this organization's name, verification is refused 409 [`org_name_taken`](/docs/api/errors#code-org-name-taken) and the claim stays pending. An already verified claim is returned as it is, with 200. Writes a `domain.verified` audit row. No body is read.

### Parameters

**`id` path · string (uuid) required**

The domain claim's id. A value that is not a UUID answers 404.

### Responses

#### `200` success

The verified claim.

As `application/json`.

**`id` string (uuid) always present**

The claim's id.

**`domain` string always present**

The domain.

**`verified_at` string (date-time) always present**

When the claim was verified.

**`verify_method` "owner\_email" | "dns\_txt" always present**

How it was verified.

**`join_policy` "off" | "request" | "auto"**

The join policy. Absent when the claim was already verified before this call.

**`default_role` "member" | "admin"**

The default role for joiners. Absent when the claim was already verified before this call.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`role_required`](/docs/api/errors#code-role-required) (the caller is a member; carries `required`), [`no_membership`](/docs/api/errors#code-no-membership), [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended), [`org_closed`](/docs/api/errors#code-org-closed), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (see `GET /v2/account/members`; `base_url` names the address that serves the key). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (no claim with that id in this organization, or `X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `409` error

Conflict. Codes: [`dns_txt_not_found`](/docs/api/errors#code-dns-txt-not-found) (no matching TXT record yet; carries `found`, the `dtg-verify=` values that were seen), [`org_name_taken`](/docs/api/errors#code-org-name-taken) (another organization that verified this domain already carries this organization's name; carries `name`, `domain`, `auto_named`; rename, then verify).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`role_required`](/docs/api/errors#code-role-required) (403), [`no_membership`](/docs/api/errors#code-no-membership) (403), [`account_suspended`](/docs/api/errors#code-account-suspended) (403), [`org_suspended`](/docs/api/errors#code-org-suspended) (403), [`org_closed`](/docs/api/errors#code-org-closed) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`dns_txt_not_found`](/docs/api/errors#code-dns-txt-not-found) (409), [`org_name_taken`](/docs/api/errors#code-org-name-taken) (409). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/orgs`

**The organizations the caller belongs to, and where a sign-in should land**

Credentials: API key or App session. Operation id `orgListMine`.

Any signed-in person, including one with no organization (then `data` is empty and `active_org_id` null) or whose only one is suspended or closed. Each row's `active` marks the organization this request resolved to (`X-DTG-Org`, else the own organization). `landing_org_id` is where a sign-in in a browser that remembers nothing should open; name it in `X-DTG-Org` to use it.

### Responses

#### `200` success

The memberships.

As `application/json`.

**`data` array of OrgMembershipSummary always present**

The caller's active memberships, own organization first, then by join date. Empty for a person with none.

**`data[].id` string (uuid) always present**

The organization's id; send it as `X-DTG-Org` to act in it.

**`data[].name` string always present**

The organization's name.

**`data[].status` "active" | "suspended" | "closed" always present**

The organization's status. `suspended`: DTG suspended it; its routes answer 403 [`account_suspended`](/docs/api/errors#code-account-suspended), [`org_suspended`](/docs/api/errors#code-org-suspended).

**`data[].role` "owner" | "admin" | "member" always present**

A member's role in an organization (ORG\_LICENSING section 7.1). `owner`: everything, including roles, ownership transfer, closing the organization and billing. `admin`: manages members, invitations, domains and join requests, but never an owner's membership. `member`: uses the product. Owners and admins always hold a seat. Billing rights are a separate flag (`billing_contact`).

**`data[].seated` boolean always present**

True when the caller holds a seat there.

**`data[].api_enabled` boolean always present**

True when the caller may hold live API keys there.

**`data[].billing_contact` boolean always present**

True when the caller is a billing contact there.

**`data[].own` boolean always present**

True for the caller's own organization (the one made at their sign-up).

**`data[].plan_code` string always present**

The organization's plan code (see `GET /v2/plans`).

**`data[].joined_at` string (date-time) always present**

When the caller joined.

**`data[].active` boolean always present**

True for the organization THIS request resolved to (`X-DTG-Org`, else the own organization). Not a membership flag; every row is an active membership.

**`active_org_id` string (uuid) or null always present**

The organization this request resolved to; null when none resolved (no membership, or the only one is suspended or closed).

**`landing_org_id` string (uuid) or null always present**

Where a sign-in in a browser that remembers nothing should open. The organization last used in a session while still a membership, else the paid organization joined most recently (unless the own one is paid), else the own. Computed from the value before this request. Null when the caller has no membership.

**`header` "X-DTG-Org" always present**

The request header that selects the organization.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve; `base_url` names the address that serves it).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (`X-DTG-Org` names an organization the caller is not an active member of, or is not a UUID).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`not_found`](/docs/api/errors#code-not-found) (404). Every problem is a [problem document](/docs/api/errors).

## GET `/v2/orgs/discover`

**Organizations at the caller's email domain that accept joins**

Credentials: API key or App session. Operation id `orgDiscover`.

Any signed-in person, including one with no organization. Lists the active organizations that have verified the caller's email domain with a join policy other than `off`. Claims are not exclusive, so several may appear; their names are unique at the domain (the name rule), and each row carries the `domain` to show beside the name. Join one with `POST /v2/orgs/{id}/join` or keep your own.

### Responses

#### `200` success

The organizations.

As `application/json`.

**`domain` string always present**

The caller's email domain, the one searched.

**`data` array of OrgDiscoverRow always present**

Active organizations with a verified claim on that domain whose join policy is not `off`, oldest first. Claims are not exclusive, so several may be listed.

**`data[].id` string (uuid) always present**

The organization's id (the `{id}` of `POST /v2/orgs/{id}/join`).

**`data[].name` string always present**

The organization's name, unique among the organizations that verified this domain.

**`data[].domain` string always present**

The verified domain the organization is listed under. Show it beside the name.

**`data[].join_policy` "request" | "auto" always present**

`auto`: joining is immediate. `request`: joining files a request an owner or admin decides.

**`data[].default_role` "member" | "admin" always present**

The role a joiner receives.

**`data[].members` integer always present**

The organization's active members.

**`data[].already_member` boolean always present**

True when the caller is already an active member.

**`data[].request_pending` boolean always present**

True when the caller has a pending join request there.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve; `base_url` names the address that serves it).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (`X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`not_found`](/docs/api/errors#code-not-found) (404). Every problem is a [problem document](/docs/api/errors).

## POST `/v2/orgs/{id}/join`

**Join an organization at your email domain, or ask to**

Credentials: API key or App session. Operation id `orgJoin`.

Any signed-in person with a verified address, including one with no organization. The organization must be one `GET /v2/orgs/discover` lists for the caller. With join policy `auto` the caller joins at once (201) with the claim's `default_role`, taking a seat when one is free (an admin is always seated) or else joining as a free member. With `request` a join request is filed (202; asking again after a denial re-opens it) and the organization's owners and admins are mailed and told in the app; they decide with `POST /v2/account/join-requests/{id}/approve` or `/deny`. No body is read.

### Parameters

**`id` path · string (uuid) required**

The organization's id, from `GET /v2/orgs/discover`. A value that is not a UUID answers 404.

### Responses

#### `201` success

Joined (join policy `auto`).

As `application/json`.

**`status` "joined" always present**

Always `joined`.

**`organization` object always present**

The organization, by id and name.

**`organization.id` string (uuid) always present**

The organization joined.

**`organization.name` string always present**

Its name.

**`membership_id` string (uuid) always present**

The new (or re-activated) membership's id.

**`seated` boolean always present**

True when a seat was taken (always for an admin; for a member only when one was free).

**`rejoined` boolean always present**

True when a former membership was re-activated rather than created.

#### `202` success

Join request filed (join policy `request`).

As `application/json`.

**`status` "requested" always present**

Always `requested`.

**`request_id` string (uuid) always present**

The join request's id.

**`organization` object always present**

The organization, by id and name.

**`organization.id` string (uuid) always present**

The organization asked.

**`organization.name` string always present**

Its name.

#### `401` error

Unauthorized. Codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (no credential, or the key or session is not valid); [`key_revoked`](/docs/api/errors#code-key-revoked) (an API key that was revoked: `revoked_at`, and `reason` -- `holder`, `admin`, `member_removed`, `seat_removed`, `api_disabled`, `addon_ended`, [`account_closed`](/docs/api/errors#code-account-closed), [`org_closed`](/docs/api/errors#code-org-closed), `retired`, or null for a key revoked before T110 -- and a sentence saying when and why).

As `application/problem+json`.

#### `403` error

Forbidden. Codes: [`email_unverified`](/docs/api/errors#code-email-unverified) (verify your address first), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (a key of the mode this process does not serve; `base_url` names the address that serves it). A sandbox key: [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (it may write only clusters).

As `application/problem+json`.

#### `404` error

Not found. Codes: [`not_found`](/docs/api/errors#code-not-found) (no organization with that id at your email domain accepts joins, or `X-DTG-Org` names an organization the caller is not an active member of).

As `application/problem+json`.

#### `409` error

Conflict. Codes: [`already_member`](/docs/api/errors#code-already-member) (the caller is already an active member; no further members).

As `application/problem+json`.

#### `429` error

rate\_limited (the per-minute ceiling, X-RateLimit-\* say which), points\_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server\_busy or sandbox\_busy (load; retry after Retry-After). A refused server\_busy request is not metered.

As `application/problem+json`.

**`Retry-After` header**

Seconds to wait before retrying.

**`X-RateLimit-Limit` header**

The per-minute request ceiling that applies.

**`X-RateLimit-Remaining` header**

Requests left in the current window.

**`X-RateLimit-Reset` header**

Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as `Retry-After`).

Problem codes: [`unauthenticated`](/docs/api/errors#code-unauthenticated) (401), [`key_revoked`](/docs/api/errors#code-key-revoked) (401), [`account_closed`](/docs/api/errors#code-account-closed) (401), [`org_closed`](/docs/api/errors#code-org-closed) (401), [`email_unverified`](/docs/api/errors#code-email-unverified) (403), [`wrong_instance`](/docs/api/errors#code-wrong-instance) (403), [`sandbox_read_only`](/docs/api/errors#code-sandbox-read-only) (403), [`not_found`](/docs/api/errors#code-not-found) (404), [`already_member`](/docs/api/errors#code-already-member) (409). Every problem is a [problem document](/docs/api/errors).

Generated from `taigan/openapi.yaml` at catahoula `77925fab712f`(API document version 2.0).
