Overview
Section titled “Overview”These endpoints let you upload, download, list, and delete files and avatars associated with notebooks in Hoody. File uploads use the TUS protocol for resumable, chunked transfers, making them suitable for large attachments. Avatar uploads accept raw image bytes and are automatically resized to 500×500 JPEG.
Use these endpoints when you need to:
- Upload files (images, documents, media) into a notebook for inclusion in pages.
- Upload or retrieve user avatar images.
- Manage resumable uploads for large files via the TUS protocol.
File Management
Section titled “File Management”GET /api/v1/notes/notebooks/{notebookId}/files
Section titled “GET /api/v1/notes/notebooks/{notebookId}/files”List all files uploaded to a notebook with limit/offset pagination.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the notebook to list files from |
limit | query | integer | No | Maximum number of files to return. Default: 50 |
offset | query | integer | No | Number of files to skip for pagination. Default: 0 |
Response
Section titled “Response”{ "files": [ { "id": "f1a2b3c4d5e6f7a8b9c0d1e2", "name": "architecture-diagram.png", "mimeType": "image/png", "size": 482104, "createdAt": "2024-09-12T14:22:07.000Z", "createdBy": "u9k8j7h6g5f4d3s2a1", "documentId": "d1c2b3a4e5f6d7c8b9a0", "documentName": "Project Architecture" }, { "id": "a9b8c7d6e5f4d3c2b1a0", "name": "meeting-notes.pdf", "mimeType": "application/pdf", "size": 102400, "createdAt": "2024-09-11T10:05:33.000Z", "createdBy": "z1y2x3w4v5u6t7s8r9", "documentId": "e5f6d7c8b9a0d1c2b3a4", "documentName": null } ], "total": 27}{ "message": "Notebook not found.", "code": "notebook_not_found", "details": [ { "path": "notebookId", "message": "No notebook with ID n1b2c3d4e5f6 exists" } ]}| Error Code | Title | Description | Resolution |
|---|---|---|---|
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify notebook ID using listNotebooks |
notebook_no_access | Access denied | User does not have permission to access files in this notebook | Check collaborator list or request access from the notebook owner |
SDK Usage
Section titled “SDK Usage”const page = await client.notes.files.listIterator({ notebookId: "n1b2c3d4e5f6", limit: 50, offset: 0,});GET /api/v1/notes/notebooks/{notebookId}/files/{fileId}
Section titled “GET /api/v1/notes/notebooks/{notebookId}/files/{fileId}”Download the binary content of an uploaded file. The response is returned with the file’s original MIME type.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the notebook that owns the file |
fileId | path | string | Yes | ID of the file to download |
Response
Section titled “Response”{ "description": "Binary file content with the original content type"}SDK Usage
Section titled “SDK Usage”const blob = await client.notes.files.download({ notebookId: "n1b2c3d4e5f6", fileId: "f1a2b3c4d5e6f7a8b9c0d1e2",});TUS Resumable Uploads
Section titled “TUS Resumable Uploads”The TUS protocol uses four HTTP methods on the same URL:
| Method | Purpose |
|---|---|
POST | Create a new upload (initializes upload metadata) |
HEAD | Check current upload offset and status |
PATCH | Upload a chunk of file data |
DELETE | Abort an in-progress upload |
All four operations share the same path and parameters.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the notebook that will own the file |
fileId | path | string | Yes | Pre-allocated ID of the file being uploaded |
POST /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus
Section titled “POST /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus”Create a new resumable upload.
{ "description": "Upload resource created; TUS headers returned in response"}await client.notes.files.tusCreateUpload({ notebookId: "n1b2c3d4e5f6", fileId: "f1a2b3c4d5e6f7a8b9c0d1e2",});HEAD /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus
Section titled “HEAD /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus”Check the current offset of an in-progress upload.
{ "description": "Response headers include Upload-Offset indicating the next byte to send"}await client.notes.files.tusCheckUpload({ notebookId: "n1b2c3d4e5f6", fileId: "f1a2b3c4d5e6f7a8b9c0d1e2",});PATCH /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus
Section titled “PATCH /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus”Upload a chunk of file data. Each request appends bytes at the server’s current Upload-Offset.
{ "description": "Chunk accepted; response headers include the new Upload-Offset"}await client.notes.files.tusUploadChunk({ notebookId: "n1b2c3d4e5f6", fileId: "f1a2b3c4d5e6f7a8b9c0d1e2",});DELETE /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus
Section titled “DELETE /api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus”Abort an in-progress upload and discard all received bytes.
{ "description": "Upload aborted; partial data discarded"}await client.notes.files.tusAbortUpload({ notebookId: "n1b2c3d4e5f6", fileId: "f1a2b3c4d5e6f7a8b9c0d1e2",});Avatar Management
Section titled “Avatar Management”POST /api/v1/notes/avatars
Section titled “POST /api/v1/notes/avatars”Upload a raw image (JPEG, PNG, or WebP) as a user avatar. The image is automatically resized to 500×500 pixels and converted to JPEG.
This endpoint takes no parameters.
Response
Section titled “Response”{ "success": true, "id": "a1b2c3d4e5f6a7b8c9d0e1f2"}{ "message": "No avatar file was uploaded.", "code": "avatar_file_not_uploaded", "details": [ { "path": "body", "message": "Request body must contain a valid JPEG, PNG, or WebP image" } ]}| Error Code | Title | Description | Resolution |
|---|---|---|---|
avatar_file_not_uploaded | Invalid upload | No file was uploaded or the content type is not a valid image | Send a multipart form with a JPEG or PNG image file |
{ "message": "Failed to upload avatar.", "code": "avatar_upload_failed", "details": [ { "path": "server", "message": "Image processing pipeline returned an error" } ]}| Error Code | Title | Description | Resolution |
|---|---|---|---|
avatar_upload_failed | Upload failed | Avatar upload failed due to a server error | Retry the upload |
SDK Usage
Section titled “SDK Usage”const result = await client.notes.avatars.upload();// result.id can be used with downloadAvatar to retrieve the imageGET /api/v1/notes/avatars/{avatarId}
Section titled “GET /api/v1/notes/avatars/{avatarId}”Download an avatar image. Returns the image as JPEG binary data.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
avatarId | path | string | Yes | ID of the avatar returned from a prior upload call |
Response
Section titled “Response”{ "description": "JPEG binary data"}SDK Usage
Section titled “SDK Usage”const blob = await client.notes.avatars.download({ avatarId: "a1b2c3d4e5f6a7b8c9d0e1f2",});