---
title: Storage
description: Per-project file storage — upload, list, delete, and link to files.
category: sdk
order: 4
agent: "@coduck/sdk/storage. list()->StoredFile[], upload(name, Blob|Buffer|Uint8Array)->StoredFile, delete(name), url(name)->string. Requires CODUCK_API_KEY (server only). 50MB/file cap; names limited to letters/digits/+._-. StoredFile{name,size,modifiedAt}."
---

# Storage

Per-project file storage for uploads, generated assets, exports — anything your app needs to keep. All methods require `CODUCK_API_KEY`, so use storage from the server.

```ts
import { storage } from '@coduck/sdk/storage';
```

## Upload

`file` can be a `Blob`, `Buffer`, or `Uint8Array`. Max **50 MB** per file. Names may contain letters, digits, and `+ . _ -`.

```ts
// e.g. inside a route handler
const form = await request.formData();
const file = form.get('file') as File;
const saved = await storage.upload(file.name, file);
// → { name, size, modifiedAt }
```

## List, link, delete

```ts
const files = await storage.list();          // StoredFile[]
const href  = storage.url('logo.png');       // direct fetch URL (needs API key header)
await storage.delete('logo.png');
```

| Method | Returns |
|---|---|
| `list()` | `StoredFile[]` |
| `upload(name, file)` | `StoredFile` |
| `delete(name)` | `void` |
| `url(name)` | `string` |

> `url(name)` returns a direct link, but fetching it requires the API key in the `Authorization` header — so serve files through your own route rather than exposing the raw URL to the browser.

## Type

```ts
interface StoredFile {
  name: string;
  size: number;       // bytes
  modifiedAt: string;
}
```
