---
title: "Cancel a scheduled deletion"
method: POST
path: "/organization/{id}/restore"
tags: ["Organizations"]
---

# Cancel a scheduled deletion

`POST /organization/{id}/restore`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/organization/{id}/restore`
- Auth: HTTP bearer

Undoes `DELETE /organization/{id}` inside its 30-day window: the purge is canceled and the organization becomes writable again. Connections do not come back, because their stored credentials were deleted at the original delete; each has to be re-authorized by hand. Requires `org:manage`, so an Org Admin can restore and not only the Owner who could delete. No body and no step-up. Refuses with `409` when the organization is not currently scheduled for deletion or the window has passed, with `403 organization_blocked` when the organization is suspended, and with `subscription_required` when the plan lapsed (the delete canceled the Stripe subscription, so a restore needs a new one).

## Path parameters

- `id` string, required

## Response `200`

OK

- object
  - `restored` true
  - `organization` Organization
    - `id` string: Organization id (`org_…`) — the value for `X-Organization-Id`.
    - `name` string
    - `slug` string: Immutable after creation.
    - `plan` string: The stored plan: `gold`, `black`, or `none` when locked. This is not the same as the effective entitlement — read `GET /organization/{id}/entitlements` before gating a feature on it.
    - `region` string, nullable: Data location fixed at creation: `us`/`eu` pin a hard jurisdiction, `apac` is a placement hint.
    - `trial_ends_at` string, date-time, nullable
    - `trial_indefinite_at` string, date-time, nullable: Set when Elaichi granted this organization an indefinite trial, otherwise null. Unlocked with no end date: no countdown, no expiry email, billing still reachable.
    - `settings` object: Free-form org settings. `PATCH /organization/{id}` REPLACES this object wholesale.
    - `logo` string, uri, nullable: Public URL of the logo image, or null.
    - `can_delete` boolean: Whether the caller may delete this organization: the `org:delete` permission, which only the Org Owner role holds. Server-computed, so branch on this rather than inspecting roles. Always `false` on rows that have no member context to compute it from, such as the organization list `GET /organization`. It never overstates: trust it when true, and read `GET /user/me` or `GET /organization/{id}` (both compute it) when you need it for a list row.
    - `can_manage` boolean: Whether the caller may change this organization's settings: the `org:manage` permission that `PATCH /organization/{id}` requires, and the organization is neither suspended nor in its deletion grace period. Server-computed, and `false` wherever `can_delete` is false for lack of a member context; it never overstates.
    - `allow_staff_impersonation` boolean: Whether Elaichi support may sign in as this organization's members to help them. `true` by default. When `false`, every request made through such a support session against this organization is refused with `403 staff_impersonation_blocked`, reads included, and the organization is left out of that session's `GET /user/me` and `GET /organization`. Changed with `PATCH /organization/{id}` (`org:manage`).
    - `mfa_required` boolean: Whether members must hold a second factor to act in this organization. `false` by default. When `true`, a signed-in session that has not shown a second factor (no TOTP challenge at login, no passkey sign-in, no factor enrolled since) is refused on every organization-scoped route, reads included, with `403 mfa_setup_required`; `error.details.has_second_factor` says whether the person already has one and only needs to sign in with it. Exempt: org API tokens, Elaichi support sessions, and a session signed in through this organization's own SSO connection. MCP connections made before it was switched on, or from a session without a factor, are refused until the person connects again. Turning it off only lifts the organization requirement: a member who set up an authenticator app of their own is still challenged for it at every non-passkey sign-in. Changed with `PATCH /organization/{id}` (`org:manage`, interactive session only).
    - `can_require_mfa` boolean: Whether the CALLER may turn `mfa_required` ON right now: `can_manage`, from an interactive session that would itself pass the check it is about to create. `false` — with the reason in `can_require_mfa_reason` — when switching it on would lock the caller out of this organization. The PATCH refuses that regardless with `409 mfa_setup_required`. Turning it OFF is not governed by this field; it needs a step-up.
    - `can_require_mfa_reason` string, nullable: A sentence saying why `can_require_mfa` is `false` for a caller who can otherwise manage the organization. `null` otherwise.
    - `deletion_scheduled_at` string, date-time, nullable: Set when a deletion has been scheduled (`DELETE /organization/{id}`). The organization is read-only until `purge_after`. Null otherwise.
    - `purge_after` string, date-time, nullable: When a scheduled deletion becomes permanent — 30 days after `deletion_scheduled_at`. Null unless scheduled.
    - `can_restore` boolean: Whether the caller may cancel a scheduled deletion: the `org:manage` permission, and only while `purge_after` is still ahead. Server-computed like `can_delete`, and `false` on rows with no member context. Read `purge_after` to tell "too late" from "not yours to undo".
    - `can_authorize_apps` boolean: Whether the CALLER may connect an app (MCP OAuth consent) to this organization right now: `false` while it is suspended, scheduled for deletion, or has no active plan. Server-computed by the same gate `POST /oauth/authorize-request/{id}/approve` calls; present only on member-scoped responses. `authorize_apps_blocked_reason` says which.
    - `authorize_apps_blocked_reason` 'blocked' | 'pending_deletion' | 'no_plan' | 'null', nullable: Why `can_authorize_apps` is `false`, in the gate's own order: `blocked`, then `pending_deletion` (even when the subscription is also gone, since a soft delete cancels it), then `no_plan`. `null` when connecting is open.
    - `created_at` string, date-time
    - `updated_at` string, date-time

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited

---

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