---
title: "List recovery operations"
method: GET
path: "/v1/recovery/operations"
tags: ["Disaster Recovery"]
---

# List recovery operations

`GET /v1/recovery/operations`

## Request

- Base URL: `https://api.subscriby.net`
- URL: `https://api.subscriby.net/v1/recovery/operations`
- Auth: HTTP bearer

```bash
curl "https://api.subscriby.net/v1/recovery/operations?kind=resources&status=completed" \
  -H "Authorization: Bearer $SUBSCRIBY_TOKEN"
```

An operation is one recovery: run by the creator, by the platform on their behalf (`automatic: true`, the failover you sleep through), or on demand (`on_demand: true`, a Swap & Grant of a healthy resource, which spends no allowance). The row exists from the moment the recovery starts, because it is the quota ledger and the audit trail at once.

Both filters are optional: `kind` is `account`, `bot` or `resources`; `status` is `started`, `completed`, `failed` or `reverted`. Newest first by `started_at`; `sort_by` also accepts `kind`, `status` and `completed_at`.

## Query parameters

- `kind` 'account' | 'bot' | 'resources': The three things a platform ban can take from a creator, and the three recoveries the Disaster Recovery Program offers for them. Declared in wizard order. The account comes first because a creator whose own identity is gone cannot act on the connector for the other two until it is replaced; the installation before the resources because customers must be able to reach it before they are re-admitted anywhere. The backing value is also the quota key: `RecoveryPolicyService` counts operations per kind, so a creator who used one kind still has the other two available inside the same window. The words a creator reads come from the connector's vocabulary, so the same case reads "Project Bot" for one connector and "Project App" for another; callers without a vocabulary at hand go through `ConnectorRecoverySupport::issueLabel()`.
- `status` 'started' | 'completed' | 'failed' | 'reverted': Where a recovery operation stands. `Started` and `Completed` both count against the self-service quota: an operation is a use the moment it begins, so an abandoned wizard cannot be restarted for free. `Failed` is the one state that gives the use back, because nothing changed. `Reverted` records that the creator undid the change inside the undo window; the use stays consumed.
- `page` integer
- `per_page` integer
- `sort_by` string
- `sort_direction` 'asc' | 'desc'

## Response `200`

The page, newest first by default.

- object
  - `data` RecoveryOperationResource[], required: The items on this page.
    - `id` string, required: The operation's id, the value the revert, nudge and notify endpoints take.
    - `kind` string, required: `account` (a sign-in relink), `bot` (a bot replacement) or `resources` (a channel swap).
    - `kind_label` string, required: The kind in the connector's own words, in the creator's language.
    - `status` string, required: `started` while the recovery runs, then `completed`, `failed` (with `failure_reason`) or `reverted`.
    - `status_label` 'In progress' | 'Completed' | 'Failed' | 'Reverted', required: The status in the creator's language.
    - `connector` string, nullable, required: The connector the recovery ran on, by key; null when it concerns no connector.
    - `project_id` string, nullable, required: The project concerned; null for an account relink.
    - `project_name` string, nullable, required: That project's name; null for an account relink.
    - `grant_id` string, nullable, required: The support grant that paid for the recovery when the self-service allowance was already spent; null otherwise.
    - `automatic` boolean, required: True when the platform ran the recovery on the creator's behalf, the failover they sleep through.
    - `on_demand` boolean, required: True for a Swap & Grant of a healthy resource, which spends no allowance.
    - `failure_reason` unknown, required
    - `started_at` string, required: When the recovery started, ISO 8601. The row exists from that moment, because it is the quota ledger and the audit trail at once.
    - `completed_at` string, nullable, required: When it finished, ISO 8601; null while running or after failing.
    - `reverted_at` string, nullable, required: When it was undone, ISO 8601; null otherwise.
    - `revertible` boolean, required: Whether the creator may still undo it **right now**: completed, of a kind that can be undone (an account relink or a channel swap, never a bot replacement), and inside the undo window. Show the undo exactly when this is true.
    - `revert_window_ends_at` string, nullable, required: When the undo window closes, ISO 8601; null for a recovery that cannot be undone.
  - `links` object, required: Links to the first, last, previous and next pages.
    - `first` string, nullable, required: The first page's URL.
    - `last` string, nullable, required: The last page's URL.
    - `prev` string, nullable, required: The previous page's URL; null on the first page.
    - `next` string, nullable, required: The next page's URL; null on the last page.
  - `meta` object, required: The paging counters for this page.
    - `current_page` integer, required: The page returned, 1-indexed.
    - `from` integer, nullable, required: The 1-indexed position of this page's first item across every page; null when the page is empty.
    - `last_page` integer, required: How many pages there are.
    - `links` object[], required: Generated paginator links.
      - `url` string, nullable, required: The page's URL; null for the ellipsis and the disabled arrows.
      - `label` string, required: The link's label: a page number, the previous or next arrow, or an ellipsis.
      - `active` boolean, required: Whether this link is the current page.
    - `path` string, nullable, required: Base path for paginator generated URLs.
    - `per_page` integer, required: Number of items shown per page.
    - `to` integer, nullable, required: Number of the last item in the slice.
    - `total` integer, required: Total number of items being paginated.

## Other responses

- `401`: `AUTHENTICATION_REQUIRED`: the request carries no bearer token, or one that is revoked, malformed, or minted for another environment (an `sbt_test_` token on production).
- `403`: `TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.
- `422`: `VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`. On this endpoint: `VALIDATION_FAILED`: when `kind` or `status` is not one of its values.
- `429`: `RATE_LIMITED`: the token has spent its 300 requests a minute or 10,000 an hour; `Retry-After` says when the next one is accepted.

---

[API](https://skmtc.dev/memberpass/apis/subscriby-rest-api.md) · [All operations](https://skmtc.dev/memberpass/apis/subscriby-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/memberpass/apis/subscriby-rest-api/revisions/59c4df91d764?raw)
