Notes: File Uploads
Section titled “Notes: File Uploads”Upload, download, and manage files and avatars attached to notebooks. File uploads use the TUS resumable upload protocol, allowing large files to be uploaded in chunks and resumed after interruption. Avatar uploads are simple raw-image POSTs that the server resizes and converts to JPEG.
All endpoints are scoped to a specific notes container and use the container’s subdomain host.
Avatars
Section titled “Avatars”GET /api/v1/notes/avatars/{avatarId}
Section titled “GET /api/v1/notes/avatars/{avatarId}”Download an avatar image. Returns the avatar as JPEG binary data.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
avatarId | path | string | Yes | Unique identifier of the avatar to download |
Response
Section titled “Response”{ "description": "Default Response"}SDK usage
Section titled “SDK usage”await client.notes.avatars.download(avatarId)curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/avatars/{avatarId}"POST /api/v1/notes/avatars
Section titled “POST /api/v1/notes/avatars”Upload an avatar image. Sends a raw image (JPEG, PNG, or WebP) which the server resizes to 500x500 and converts to JPEG. Use a multipart form upload — the field name is not constrained by this API.
This endpoint takes no parameters.
Response
Section titled “Response”{ "success": true, "id": "avatar_8f3c2a1b9e4d7f6a"}{ "message": "No avatar file was uploaded.", "code": "avatar_file_not_uploaded", "details": [ { "path": "file", "message": "No file was uploaded or the content type is not a valid 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": "file", "message": "Server error while processing the avatar upload" } ]}| 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”await client.notes.avatars.upload()curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/avatars" \ -F "avatar=@./profile.jpg;type=image/jpeg"GET /api/v1/notes/notebooks/{notebookId}/files
Section titled “GET /api/v1/notes/notebooks/{notebookId}/files”List all uploaded files for a notebook. Returns a paginated list using limit and offset query parameters.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Unique identifier of the notebook |
limit | query | integer | No | Maximum number of files to return. Default: 50 |
offset | query | integer | No | Number of files to skip before returning results. Default: 0 |
Response
Section titled “Response”{ "files": [ { "id": "file_7a2b9c4e1f8d3a5b", "name": "whitepaper-draft.pdf", "mimeType": "application/pdf", "size": 1843200, "createdAt": "2025-01-15T10:32:18.000Z", "createdBy": "user_3f8a1b2c4d5e6f7g", "documentId": "doc_9c8e7f6a5b4d3c2e", "documentName": "Project Whitepaper" }, { "id": "file_6d1e8c3b9a7f2e4d", "name": "meeting-notes.png", "mimeType": "image/png", "size": 245678, "createdAt": "2025-01-14T16:05:42.000Z", "createdBy": "user_3f8a1b2c4d5e6f7g", "documentId": "doc_4f3e2d1c9b8a7f6e", "documentName": null } ], "total": 17}{ "message": "Notebook not found.", "code": "notebook_not_found", "details": [ { "path": "notebookId", "message": "No notebook exists with the provided ID" } ]}| 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”await client.notes.files.listIterator(notebookId)
// With paginationawait client.notes.files.listIterator(notebookId, { limit: 20, offset: 40 })curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/notebooks/{notebookId}/files?limit=50&offset=0"GET /api/v1/notes/notebooks/{notebookId}/files/{fileId}
Section titled “GET /api/v1/notes/notebooks/{notebookId}/files/{fileId}”Download the content of a previously uploaded file. Returns binary data with the original content type.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Unique identifier of the notebook that owns the file |
fileId | path | string | Yes | Unique identifier of the file to download |
Response
Section titled “Response”{ "description": "Default Response"}SDK usage
Section titled “SDK usage”await client.notes.files.download(fileId, notebookId)curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/notebooks/{notebookId}/files/{fileId}" \ -o downloaded-fileTUS Resumable Uploads
Section titled “TUS Resumable Uploads”Large file uploads use the TUS protocol. Each upload has four lifecycle operations that all share the same path. The fileId is a client-generated upload identifier used to track and resume the upload.
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. The TUS protocol uses this call to register a new upload and obtain the server-side resource URL.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Unique identifier of the notebook |
fileId | path | string | Yes | Client-generated identifier for the upload session |
Response
Section titled “Response”{ "description": "Default Response"}SDK usage
Section titled “SDK usage”await client.notes.files.tusCreateUpload(notebookId, fileId)curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus" \ -H "Tus-Resumable: 1.0.0" \ -H "Upload-Length: 10485760" \ -H "Upload-Metadata: filename cHJvamVjdC56aXA=,mimeType YXBwbGljYXRpb24vemlw"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 to an existing TUS upload. The server uses the Upload-Offset header to track how many bytes have been received and supports resuming after disconnects.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Unique identifier of the notebook |
fileId | path | string | Yes | Identifier of the upload session created via POST |
Response
Section titled “Response”{ "description": "Default Response"}SDK usage
Section titled “SDK usage”await client.notes.files.tusUploadChunk(notebookId, fileId)curl -X PATCH "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus" \ -H "Tus-Resumable: 1.0.0" \ -H "Upload-Offset: 0" \ -H "Content-Type: application/offset+octet-stream" \ --data-binary @chunk-0.binHEAD /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. Used to resume an interrupted upload by querying how many bytes the server has already received.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Unique identifier of the notebook |
fileId | path | string | Yes | Identifier of the upload session |
Response
Section titled “Response”{ "description": "Default Response"}SDK usage
Section titled “SDK usage”await client.notes.files.tusCheckUpload(notebookId, fileId)curl -I "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus" \ -H "Tus-Resumable: 1.0.0"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 any partial data on the server.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Unique identifier of the notebook |
fileId | path | string | Yes | Identifier of the upload session to abort |
Response
Section titled “Response”{ "description": "Default Response"}SDK usage
Section titled “SDK usage”await client.notes.files.tusAbortUpload(notebookId, fileId)curl -X DELETE "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.icu/api/v1/notes/notebooks/{notebookId}/files/{fileId}/tus" \ -H "Tus-Resumable: 1.0.0"