Notes: Databases
Section titled “Notes: Databases”The Notes Databases API provides full CRUD operations over the records stored inside notebook database nodes. Use these endpoints to list, search, create, update, and delete individual rows, including their typed field values. All endpoints are scoped to a notebook and database combination and require permission to access the parent node.
Records
Section titled “Records”List records
Section titled “List records”GET /api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records
Returns a paginated list of records in a database. Supports JSON-encoded filters and sorts.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
filters | query | string | No | JSON-encoded filter expression applied to the record set |
sorts | query | string | No | JSON-encoded sort directives |
page | query | integer | No | Page number (default 1) |
count | query | integer | No | Number of records per page (default 50) |
notebookId | path | string | Yes | ID of the parent notebook |
databaseId | path | string | Yes | ID of the database node |
Response
Section titled “Response”{ "records": [ { "id": "65f1a2b3c4d5e6f7a8b9c0d1", "name": "Quarterly planning", "avatar": null, "fields": { "status": { "type": "string", "value": "In Progress" }, "priority": { "type": "number", "value": 3 } } } ], "total": 1, "page": 1, "count": 50}| Field | Type | Required | Description |
|---|---|---|---|
records | array | Yes | Array of record objects |
total | integer | Yes | Total number of records matching the query |
page | integer | Yes | Current page number |
count | integer | Yes | Requested page size; the records array may contain fewer items |
{ "message": "Invalid JSON in filters parameter.", "code": "bad_request", "details": [ { "path": "filters", "message": "Unexpected token at position 4" } ]}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Invalid filter or sort parameters | The filters or sorts query parameter contains invalid JSON | Verify the JSON structure of filter and sort parameters |
{ "message": "You do not have access to this node.", "code": "forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |
notebook_no_access | No access to notebook | The notebook exists but the caller is not a member, or it is not open | Verify user identity or request access from the owner |
{ "message": "Database not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Database not found | No database node exists with the provided ID | Verify database ID using client.notes.nodes.list() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
SDK usage
Section titled “SDK usage”curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records?page=1&count=50" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.notes.records.listIterator(notebookId, databaseId, { page: 1, count: 50 })) { console.log(item);}Get a record
Section titled “Get a record”GET /api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/{recordId}
Returns a single record by ID from a database.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the parent notebook |
databaseId | path | string | Yes | ID of the database node |
recordId | path | string | Yes | ID of the record to retrieve |
Response
Section titled “Response”{ "id": "65f1a2b3c4d5e6f7a8b9c0d1", "name": "Quarterly planning", "avatar": null, "fields": { "status": { "type": "string", "value": "In Progress" }, "owner": { "type": "string", "value": "Alex Morgan" }, "tags": { "type": "string_array", "value": ["planning", "Q4"] }, "priority": { "type": "number", "value": 3 }, "done": { "type": "boolean", "value": false } }}{ "message": "You do not have access to this node.", "code": "forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |
notebook_no_access | No access to notebook | The notebook exists but the caller is not a member, or it is not open | Verify user identity or request access from the owner |
{ "message": "Record not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Record not found | No record with the given ID exists in the database | Verify record ID using client.notes.records.list() or client.notes.records.search() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
SDK usage
Section titled “SDK usage”curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/{recordId}" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.notes.records.get(notebookId, databaseId, recordId);Search records
Section titled “Search records”GET /api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/search
Searches records in a database by name. Supports excluding specific record IDs.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | No | Search query matched against record names (default "") |
exclude | query | string | No | JSON-encoded array of record IDs to omit from results |
notebookId | path | string | Yes | ID of the parent notebook |
databaseId | path | string | Yes | ID of the database node |
Response
Section titled “Response”{ "records": [ { "id": "65f1a2b3c4d5e6f7a8b9c0d1", "name": "Quarterly planning", "fields": { "status": { "type": "string", "value": "In Progress" } } } ], "total": 1}| Field | Type | Required | Description |
|---|---|---|---|
records | array | Yes | Array of record objects matching the search query |
total | integer | Yes | Total number of matching records |
{ "message": "Invalid JSON in exclude parameter.", "code": "bad_request", "details": [ { "path": "exclude", "message": "Expected an array of strings" } ]}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Invalid exclude parameter | The exclude query parameter contains invalid JSON | Provide a valid JSON array of record IDs to exclude |
{ "message": "You do not have access to this node.", "code": "forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |
notebook_no_access | No access to notebook | The notebook exists but the caller is not a member, or it is not open | Verify user identity or request access from the owner |
{ "message": "Database not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Database not found | No database node exists with the provided ID | Verify database ID using client.notes.nodes.list() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
SDK usage
Section titled “SDK usage”curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/search?q=planning" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.notes.records.search(notebookId, databaseId, { q: 'planning' });Create a record
Section titled “Create a record”POST /api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records
Creates a new record in a database with a name and custom field values.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the parent notebook |
databaseId | path | string | Yes | ID of the database node |
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | No | Optional client-supplied record ID | |
name | string | No | "Untitled" | Display name for the record |
avatar | string | null | No | Avatar reference for the record | |
fields | object | No | {} | Map of field names to typed values |
Response
Section titled “Response”{ "id": "65f1a2b3c4d5e6f7a8b9c0d1", "name": "Quarterly planning", "avatar": null, "fields": { "status": { "type": "string", "value": "In Progress" }, "priority": { "type": "number", "value": 3 } }}{ "message": "Invalid request body.", "code": "bad_request", "details": [ { "path": "fields.priority", "message": "Expected an object" } ]}{ "message": "You do not have permission to perform this action.", "code": "forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |
forbidden | Insufficient permissions | User role does not have permission for this action | Request a higher role from the notebook or node admin |
notebook_no_access | No access to notebook | The notebook exists but the caller is not a member, or it is not open | Verify user identity or request access from the owner |
{ "message": "Database not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Database not found | No database node exists with the provided ID | Verify database ID using client.notes.nodes.list() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
{ "message": "Idempotency key conflict.", "code": "bad_request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Idempotency conflict | A different request was already made with the same idempotency key | Use a new idempotency key for a different request |
{ "message": "An unexpected error occurred.", "code": "unknown"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
unknown | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |
SDK usage
Section titled “SDK usage”curl -X POST "https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Quarterly planning", "fields": { "status": { "type": "string", "value": "In Progress" }, "priority": { "type": "number", "value": 3 } } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.notes.records.create(notebookId, databaseId, { name: 'Quarterly planning', fields: { status: { type: 'string', value: 'In Progress' }, priority: { type: 'number', value: 3 } }});Update a record
Section titled “Update a record”PATCH /api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/{recordId}
Updates a record name, avatar, or field values. Fields are merged with existing values.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the parent notebook |
databaseId | path | string | Yes | ID of the database node |
recordId | path | string | Yes | ID of the record to update |
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | No | New display name for the record | |
avatar | string | null | No | New avatar reference for the record | |
fields | object | No | Map of field names to typed values. Each value is an object of shape { type, value } where type is one of "boolean", "string", "string_array", "number", or "text". Field values are merged into the existing record. |
Response
Section titled “Response”{ "id": "65f1a2b3c4d5e6f7a8b9c0d1", "name": "Quarterly planning (revised)", "avatar": null, "fields": { "status": { "type": "string", "value": "Done" }, "priority": { "type": "number", "value": 3 } }}{ "message": "Invalid field value type.", "code": "bad_request", "details": [ { "path": "fields.done", "message": "Field type 'bool' is not supported" } ]}{ "message": "You do not have permission to perform this action.", "code": "forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |
forbidden | Insufficient permissions | User role does not have permission for this action | Request a higher role from the notebook or node admin |
notebook_no_access | No access to notebook | The notebook exists but the caller is not a member, or it is not open | Verify user identity or request access from the owner |
{ "message": "Record not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Record not found | No record with the given ID exists in the database | Verify record ID using client.notes.records.list() or client.notes.records.search() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
{ "message": "An unexpected error occurred.", "code": "unknown"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
unknown | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |
SDK usage
Section titled “SDK usage”curl -X PATCH "https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/{recordId}" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Quarterly planning (revised)", "fields": { "status": { "type": "string", "value": "Done" } } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.notes.records.update(notebookId, databaseId, recordId, { name: 'Quarterly planning (revised)', fields: { status: { type: 'string', value: 'Done' } }});Delete a record
Section titled “Delete a record”DELETE /api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/{recordId}
Permanently deletes a record from a database.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | ID of the parent notebook |
databaseId | path | string | Yes | ID of the database node |
recordId | path | string | Yes | ID of the record to delete |
Response
Section titled “Response”{ "success": true}| Field | Type | Required | Description |
|---|---|---|---|
success | boolean | Yes | Whether the record was deleted |
{ "message": "You do not have permission to perform this action.", "code": "forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Insufficient permissions | User role does not have permission for this action | Request a higher role from the notebook or node admin |
notebook_no_access | No access to notebook | The notebook exists but the caller is not a member, or it is not open | Verify user identity or request access from the owner |
{ "message": "Record not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Record not found | No record with the given ID exists in the database | Verify record ID using client.notes.records.list() or client.notes.records.search() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
{ "message": "An unexpected error occurred.", "code": "unknown"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
unknown | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |
SDK usage
Section titled “SDK usage”curl -X DELETE "https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records/{recordId}" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.notes.records.delete(notebookId, databaseId, recordId);