# read_storage_backup_file

Source: https://modulify.ai/docs/api/backups/read-storage-backup-file

Reads one file out of a storage backup as plain text, without changing anything.

- Title: Read a file from a storage backup
- Scope: `data:read`
- Access: Read only
- Endpoint: `POST /v1/read_storage_backup_file`

Pass a `backupId` from `list_storage_backups` and the exact `key` that `browse_storage_backup` returned. This answers what a file looked like before: the client can read the old version, compare it with the file as it stands now and say what changed, or write the old content back itself rather than restoring anything. It needs only workspace membership and works on any plan.

Text files come back in `content` as plain text, never base64, capped at the first 32 KB, with `truncated` true and `bytesReturned` saying how much came back when the file is larger. There is no way to read past that cap, so a longer file has to be downloaded whole from **Browse files** in the editor.

Anything that is not text, such as an image, a video, an audio file, a PDF or a file with no readable extension, is not fetched at all: `readable` comes back false, `content` is null, and `kind` and `size` say what it is. That is a successful answer rather than an error, and the tool tells the client to report the name, size and type and never to invent the contents of a file it was not given.

It reads the file as the backup holds it, which is not the file in the storage now, and a private file can be read here, so the tool tells the client to treat what comes back as your own data. A backup still being archived, one that failed, or one taken in an older format is refused with the reason, and a key that is not in the archive answers `That file is not in this backup!` See [Browsing a backup from chat](https://modulify.ai/docs/editor/backups#browsing-a-backup-from-chat).

## Request

Call it with a `POST` to `https://api.modulify.ai/v1/read_storage_backup_file`, sending the inputs below as a JSON object. The token needs the `data:read` scope.

It only reads and changes nothing, so retrying it is safe.

```bash
curl -X POST https://api.modulify.ai/v1/read_storage_backup_file \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"PROJECT_ID","backupId":"BACKUP_ID","key":"KEY"}'
```

Over MCP, the same method is the [read_storage_backup_file tool](https://modulify.ai/docs/mcp/backups/read-storage-backup-file).

## Inputs

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string | Yes | The site the backup belongs to. |
| `backupId` | string | Yes | The backup to read the file out of, from `list_storage_backups`. |
| `key` | string | Yes | The full key of the file, exactly as `browse_storage_backup` returned it. |

## Response

Every call answers with the [JSON envelope](https://modulify.ai/docs/api/requests-and-responses#the-response) of `success`, `message`, `data`, `code` and `version`. `data` holds the result described above, and on a method that returns a total, `count` carries it. The [response headers](https://modulify.ai/docs/api/requests-and-responses#headers-on-every-method-call) carry the call's `X-Request-Id` and what is left of your per-minute budget in `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. [Errors](https://modulify.ai/docs/api/errors) explains every status code a call can answer with.