# Uploads API

Uploads is DevBlanket's file storage and management service.

> **First time here?** Read the [DevBlanket API Overview](https://devblanket.com) first. It explains authentication, how to get your org ID from Door's `/api/me` endpoint, and the conventions shared across all DevBlanket services.

## Authentication

Use your Extra Key as a Bearer token:

```
Authorization: Bearer <your-extra-key>
```

## Key Endpoints

All file operations are scoped to an organization. Get your `orgId` from Door's `/api/me` endpoint.

### List Files

```
GET /api/orgs/:orgId/files
```

Query parameters:
- `limit` - Max files to return (default 24, max 100)
- `cursor` - Pagination cursor from previous response
- `sort` - Sort by: filename, mimeType, size, createdAt (default)
- `dir` - Sort direction: asc, desc (default)
- `type` - Filter by MIME type prefix (e.g., `image/`)
- `search` - Search filename (case-insensitive)

### Upload File

```
POST /api/orgs/:orgId/files
Content-Type: multipart/form-data

file: <binary>
isPublic: true|false (optional)
```

Returns the created file metadata including `id` and URLs.

### Get File Metadata

```
GET /files/:fileId/metadata
```

### Delete File

```
DELETE /api/orgs/:orgId/files/:fileId
```

### Download File

```
GET /files/:fileId
```

Query parameters:
- `thumb=true` - Get thumbnail (images only)
- `download=true` - Force download vs inline display

Public files can be accessed without authentication.

### Get Aliases for a File

```
GET /api/orgs/:orgId/files/:fileId/aliases
```

Returns all aliases pointing to a specific file. Useful for understanding file usage before deletion.

## Aliases

Aliases create semantic URLs for files, enabling clean paths like `/sandscript/mod.js`.

### List Aliases

```
GET /api/orgs/:orgId/aliases
```

Query parameters:
- `limit` - Max results (default 50, max 100)
- `cursor` - Pagination cursor (path to continue from)
- `prefix` - Filter by path prefix (e.g., `sandscript/`)
- `search` - Substring search in path
- `fileId` - Find aliases pointing to a specific file

Response includes pagination info:
```json
{
  "aliases": [...],
  "pagination": { "hasMore": true, "cursor": "path/to/continue" }
}
```

### Directory-style Listing

Navigate aliases like a filesystem:

```
GET /api/orgs/:orgId/aliases/list
GET /api/orgs/:orgId/aliases/list/:path
```

Examples:
```
GET /api/orgs/:orgId/aliases/list           # Root level
GET /api/orgs/:orgId/aliases/list/sandscript  # Contents of sandscript/
```

Response:
```json
{
  "path": "sandscript",
  "entries": [
    {
      "name": "mod.js",
      "type": "file",
      "alias": { "id": "...", "path": "sandscript/mod.js", ... },
      "file": { "id": "...", "filename": "...", "mimeType": "...", "size": 1234 }
    },
    {
      "name": "utils",
      "type": "directory",
      "count": 3
    }
  ]
}
```

### Tree View (LLM-optimized)

Get the full alias namespace as a nested tree structure:

```
GET /api/orgs/:orgId/aliases/tree
```

Query parameters:
- `path` - Start from a subtree (default: root)
- `maxDepth` - How deep to recurse (default: 3, max: 10)
- `maxEntries` - Total entries before truncation (default: 100, max: 500)

Response:
```json
{
  "path": "",
  "truncated": false,
  "totalAliases": 25,
  "tree": {
    "sandscript": {
      "_type": "directory",
      "_count": 5,
      "mod.js": {
        "_type": "file",
        "_aliasId": "...",
        "_fileId": "...",
        "_mimeType": "application/javascript",
        "_size": 1234
      },
      "utils": {
        "_type": "directory",
        "_count": 2,
        "_truncated": true
      }
    }
  }
}
```

### Statistics

Get aggregated alias statistics:

```
GET /api/orgs/:orgId/aliases/stats
```

Response:
```json
{
  "totalAliases": 101,
  "totalDirectories": 13,
  "aliasesWithCustomHeaders": 4,
  "mostRecentUpdate": "2026-01-19T15:11:27.741Z",
  "topLevelPaths": ["components", "sandscript", "libraries"],
  "byMimeType": { "application/javascript": 19, "text/javascript": 38 }
}
```

### Bulk Operations

Create, update, or delete multiple aliases in one request:

```
POST /api/orgs/:orgId/aliases/batch
{
  "operations": [
    { "action": "create", "path": "v2/mod.js", "fileId": "abc123" },
    { "action": "update", "path": "v1/mod.js", "fileId": "xyz789" },
    { "action": "delete", "path": "deprecated/old.js" }
  ]
}
```

Response:
```json
{
  "results": [
    { "action": "create", "path": "v2/mod.js", "success": true, "alias": {...} },
    { "action": "update", "path": "v1/mod.js", "success": true, "alias": {...} },
    { "action": "delete", "path": "deprecated/old.js", "success": true }
  ],
  "summary": { "created": 1, "updated": 1, "deleted": 1, "failed": 0 }
}
```

Max 100 operations per request. Operations are executed sequentially (not transactional).

### Create Alias

```
POST /api/orgs/:orgId/aliases
{
  "fileId": "...",
  "path": "images/logo.png",
  "headers": { "Cache-Control": "public, max-age=31536000" }
}
```

### Move/Rename Alias

```
POST /api/orgs/:orgId/aliases/:aliasId/move
{ "newPath": "v2/renamed.js" }
```

Renames an alias to a new path. Preserves history.

### Copy Alias

```
POST /api/orgs/:orgId/aliases/:aliasId/copy
{ "newPath": "backup/copy.js" }
```

Creates a new alias pointing to the same file. Useful for versioning.

### Access via Clean URL

```
https://item.devblanket.com/:org-slug/:path
```

Example: `https://item.devblanket.com/devblanket-hq/sandscript/mod.js`

## OpenAPI Schema

Full API specification available at:

```
GET /openapi.json
```

## Error Format

```json
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Error message",
    "requestId": "..."
  }
}
```
