---
title: "Restore a deleted record"
method: POST
path: "/knowledgeBase/record/{recordId}/restore"
tags: ["Knowledge Base"]
---

# Restore a deleted record

`POST /knowledgeBase/record/{recordId}/restore`

## Request

- Base URL: `https://app.pipeshub.com/api/v1`
- URL: `https://app.pipeshub.com/api/v1/knowledgeBase/record/{recordId}/restore`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `/api/v1/oauth2/authorize`
    - Client credentials
    - Token URL: `/api/v1/oauth2/token` scopes: `kb:delete`

Bring a record back from the trash, together with everything deleted in the
same action: a folder comes back with its contents, a file with its
attachments, a multi-select delete with every item it removed.

Needs "Move Deleted Records to the Trash" on in Labs.

**Required permission:** the role the delete needed. A single file needs
OWNER, WRITER or FILEORGANIZER on its collection; a folder or several items
need OWNER or WRITER.

**Names:** an item whose name another item next to it now uses comes back
as "name (restored)" (a file keeps its extension: "report (restored).pdf").

**Search:** restored files are indexed again, so they return to search and
chat once indexing finishes. `reindexPending` lists any that could not be
queued; reindex those by hand. A file that is back but whose indexing never
started is queued again when it is restored again, and the indexing service
queues it on its own after about an hour.

A record that is not in the trash answers 200 with nothing restored.
The query string and any request body are ignored.

## Path parameters

- `recordId` string, required

## Response `200`

Record restored, with everything deleted along with it

- RestoreRecordResponseSchema: Response returned by POST /knowledgeBase/record/{recordId}/restore.
  - `success` true, required
  - `message` string, required
  - `batchId` string, nullable: The delete batch that was restored
  - `restoredRecords` RestoredRecordSchema[], required
    - `recordId` string, required
    - `name` string, nullable: The name it has now
    - `renamedFrom` string: Its name before restore, when another item next to it had taken that name
  - `reindexPending` boolean: Some restored files could not be queued for indexing
  - `reindexPendingRecordIds` string[]: Files to reindex by hand to make them searchable again
  - `reindexPendingReason` string
  - `renamePendingRecordIds` string[]: Items restored under a name another item next to them has; rename them
  - `renamePendingReason` string

## Other responses

- `400`: `recordId` holds a character that cannot stand in a URL path segment (`/`, `\`, `?`, `#`, `%`, a control character) or is `.` or `..` (`HTTP_BAD_REQUEST`) Also returned, before authentication, when a query value, or any string in a JSON or form-encoded body, looks like markup to the app-wide XSS filter: an HTML tag, a script tag, `<iframe`, `<object`, `<embed` or `<svg` tag, a word starting with `on` followed by `=` (meant for inline event handlers such as `onerror=`, it also catches plain text such as `one=1`), a `javascript:` or `data:text/html` URL, an encoded script tag (`&lt;script`, `%3cscript`), or any string longer than 100,000 characters (`HTTP_BAD_REQUEST`, "HTML tags, scripts, and XSS content are not allowed in ...", naming the field or query parameter; a string over 100,000 characters is refused as too long instead). A JSON body that does not parse is refused the same way, also before authentication (`HTTP_BAD_REQUEST`, "The request body is not valid JSON.").
- `401`: Missing, invalid, expired, or revoked authentication
- `403`: Not allowed. The message says why and what to do: restoring is turned off in Labs (ask an admin to turn on "Move Deleted Records to the Trash"), the caller lacks edit access to the collection (ask its owner), the record comes from a connected app (restore it in that app; it returns at the next sync), or the OAuth token is missing the kb:delete scope.
- `404`: No such record in this workspace, or it was removed for good when the trash was emptied. A caller with no role on the record's collection also gets `404` (`Knowledge base not found`).
- `409`: Nothing was restored. The message says what to do: the folder the record was in is still in the trash (restore that folder first), another item has taken this record's place (delete that item first, then restore), or the record changed while it was being restored (refresh and try again). The knowledge base is being deleted (`error.code` is `HTTP_KB_BEING_DELETED`): it can no longer be changed. Reads still work and show `status: DELETING`; retry the delete instead.
- `500`: Internal server error while restoring the record. A JSON body larger than 10 MB, or a form-encoded body larger than 100 KB or with more than 1000 fields, is answered `413` by the app-wide body parsers instead, also before authentication.
- `503`: Connector service unavailable or connection refused

## Changes

- **2026-10-28** `dbb5e203b445`: 1 info
  - added the non-success response with the status `400`
- **2026-10-13** `bb0c59adf026`: 1 info
  - endpoint added
- **2026-10-08** `c462bea9ad26`: 1 breaking
  - api path removed without deprecation
- **2026-10-08** `bb0c59adf026`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/pipeshub-ai/apis/pipeshub-api/changes/knowledgeBase/record/:recordId/restore/post.md)

---

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