Notes: nodes & documents
Section titled “Notes: nodes & documents”The Notes service organizes content as a tree of nodes within a notebook. Each node has a type such as page, section, channel, message, database, or record. Document-bearing nodes (pages, channels, and similar) carry rich-text content. This page covers node lifecycle, document read and write, secure HTML export, drawing block rendering, and per-user interaction tracking.
GET /api/v1/notes/notebooks/{notebookId}/nodes
Section titled “GET /api/v1/notes/notebooks/{notebookId}/nodes”Returns a paginated list of nodes the user has access to. Filterable by type, parentId, and rootId.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
type | query | string | No | Filter by node type |
parentId | query | string | No | Filter by direct parent |
rootId | query | string | No | Filter by root ancestor |
limit | query | integer | No | Maximum number of nodes to return. Default 50 |
offset | query | integer | No | Number of nodes to skip. Default 0 |
curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes?type=page&limit=25" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
const result = await client.notes.nodes.list("nb_abc123", { type: "page", limit: 25 });Response
Section titled “Response”{ "nodes": [ { "id": "node_8f3a2b", "type": "page", "name": "Onboarding", "parentId": "node_root01", "rootId": "node_root01", "alias": "onboarding", "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1", "updatedAt": "2026-09-15T08:02:11.000Z", "updatedBy": "user_owner_1" }, { "id": "node_55cc91", "type": "page", "name": "Architecture", "parentId": "node_root01", "rootId": "node_root01", "alias": "architecture", "createdAt": "2026-09-13T14:48:00.000Z", "createdBy": "user_owner_1", "updatedAt": null, "updatedBy": null } ], "total": 2}{ "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 |
{ "code": "notebook_not_found", "message": "Notebook not found."}| Error Code | Title | Description | Resolution |
|---|---|---|---|
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
GET /api/v1/notes/notebooks/{notebookId}/nodes/alias/{alias}
Section titled “GET /api/v1/notes/notebooks/{notebookId}/nodes/alias/{alias}”Resolves a page node by its safe alias within the notebook scope.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
alias | path | string | Yes | Safe alias of the page node |
curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/alias/onboarding" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.resolve('nb_abc123', 'onboarding');Response
Section titled “Response”{ "id": "node_8f3a2b", "type": "page", "name": "Onboarding", "alias": "onboarding", "parentId": "node_root01", "rootId": "node_root01", "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1"}{ "code": "bad_request", "message": "Invalid page alias."}{ "code": "notebook_no_access", "message": "You do not have access to this notebook."}| Error Code | Title | Description | Resolution |
|---|---|---|---|
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 |
No page in the notebook has that alias:
{ "code": "not_found", "message": "Page alias not found."}The notebook does not exist:
{ "code": "notebook_not_found", "message": "Notebook not found."}| Error Code | Title | Description | Resolution |
|---|---|---|---|
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}
Section titled “GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}”Returns the full details of a single node by ID.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.get('nb_abc123', 'node_8f3a2b');Response
Section titled “Response”{ "id": "node_8f3a2b", "type": "page", "name": "Onboarding", "alias": "onboarding", "parentId": "node_root01", "rootId": "node_root01", "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1", "updatedAt": "2026-09-15T08:02:11.000Z", "updatedBy": "user_owner_1"}{ "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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/children
Section titled “GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/children”Returns a paginated list of direct children of the specified node.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the parent node |
limit | query | integer | No | Maximum number of children to return. Default 50 |
offset | query | integer | No | Number of children to skip. Default 0 |
curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_root01/children?limit=10" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
const children = await client.notes.nodes.listChildren("nb_abc123", "node_root01", { limit: 10 });Response
Section titled “Response”{ "nodes": [ { "id": "node_8f3a2b", "type": "page", "name": "Onboarding", "parentId": "node_root01" }, { "id": "node_55cc91", "type": "page", "name": "Architecture", "parentId": "node_root01" } ], "total": 2}{ "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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
POST /api/v1/notes/notebooks/{notebookId}/nodes
Section titled “POST /api/v1/notes/notebooks/{notebookId}/nodes”Creates a new node (section, page, channel, message, database, or record) in the notebook. Every type except section needs a parentId, such as the notebook’s Home section for a page, folder, database or channel. A section can only sit at the root, so it takes no parentId; without attributes.collaborators the caller becomes its admin.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
X-Idempotency-Key | header | string | No | Optional idempotency key (max 256 chars), such as a random UUID per node. Reusing the same key with an identical request body replays the original response instead of creating a second node; reusing it with a different body returns 409. |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
type | Yes | string | Node type, for example page, section, channel, message, database, or record |
attributes | Yes | object | Node attributes (name, description, alias, and other type-specific fields) |
id | No | string | Optional client-supplied node identifier |
parentId | No | string | Identifier of the parent node |
curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "type": "page", "parentId": "node_root01", "attributes": { "name": "Roadmap", "alias": "roadmap", "description": "Quarterly roadmap notes" } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.create('nb_abc123', { type: 'page', parentId: 'node_root01', attributes: { name: 'Roadmap', alias: 'roadmap', description: 'Quarterly roadmap notes', },});Response
Section titled “Response”{ "id": "node_77ab02", "type": "page", "name": "Roadmap", "alias": "roadmap", "parentId": "node_root01", "rootId": "node_root01", "createdAt": "2026-09-16T11:00:00.000Z", "createdBy": "user_owner_1"}{ "message": "Invalid node type.", "code": "bad_request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Invalid node data | The request body is invalid, missing required fields or uses an unsupported node type | Check the node type is valid and all required attributes are provided |
parent_required | Parent required | Every node type except a section goes under a parent node, and the request has no parentId | Pass parentId, for example the notebook’s Home section id for a page |
section_must_be_root | Section must be at the root | A section sits at the root of the notebook, and the request has a parentId | Omit parentId when creating a section |
{ "message": "You do not have permission to create this node.", "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 |
{ "code": "notebook_not_found", "message": "Notebook not found."}| Error Code | Title | Description | Resolution |
|---|---|---|---|
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 |
PATCH /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}
Section titled “PATCH /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}”Updates node attributes (name, description, alias, and so on). type, parentId, and databaseId sent in attributes are ignored rather than refused.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
attributes | Yes | object | Partial or full set of node attributes to merge |
curl -X PATCH "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "attributes": { "name": "Onboarding (revised)", "description": "Updated onboarding steps for Q4" } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.update('nb_abc123', 'node_8f3a2b', { attributes: { name: 'Onboarding (revised)', description: 'Updated onboarding steps for Q4', },});Response
Section titled “Response”{ "id": "node_8f3a2b", "type": "page", "name": "Onboarding (revised)", "description": "Updated onboarding steps for Q4", "parentId": "node_root01", "updatedAt": "2026-09-16T11:14:00.000Z", "updatedBy": "user_owner_1"}{ "message": "Invalid page alias. Use lowercase letters, numbers, \"_\" or \"-\", and avoid reserved aliases.", "code": "bad_request"}{ "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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
{ "message": "Page alias already exists in this notebook.", "code": "bad_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 |
DELETE /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}
Section titled “DELETE /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}”Permanently deletes a node and its associated data (documents, files, reactions).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
curl -X DELETE "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.delete('nb_abc123', 'node_8f3a2b');Response
Section titled “Response”{ "success": true}{ "message": "You do not have permission to delete this node.", "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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
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 |
Documents
Section titled “Documents”GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document
Section titled “GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document”Retrieves document content for a node. Supports block filtering via blockIds, line range queries, and HTML/Markdown output for export pipelines.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
blockIds | query | string | No | Comma-separated list of block IDs to include |
lines | query | string | No | Line range, for example 1-40 |
output | query | string | No | Output format. One of json, md, html |
includeComments | query | string | No | Whether to include comments. One of none, appendix. Default none |
ticket | query | string | No | Export ticket returned by createExportTicket (required when output=html) |
If-None-Match | header | string | No | Optional (RFC 9110): ETags of copies the caller already holds, or *. When the document is still at one of them the JSON output answers 304 with no body. Ignored by the Markdown and HTML outputs. |
curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/document?output=md&includeComments=none" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.get('nb_abc123', 'node_8f3a2b', { output: 'md', includeComments: 'none' });Response
Section titled “Response”{ "id": "node_8f3a2b", "content": { "type": "rich_text", "blocks": { "b_welcome": { "id": "b_welcome", "type": "heading1", "parentId": "node_8f3a2b", "index": "a0", "content": [ { "type": "text", "text": "Welcome to the project" } ] }, "b_intro": { "id": "b_intro", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a1", "content": [ { "type": "text", "text": "This page outlines our onboarding process." } ] } } }, "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1", "updatedAt": "2026-09-15T08:02:11.000Z", "updatedBy": "user_owner_1"}The document is still at an ETag given in If-None-Match (JSON output only): headers only, no body. The ETag header carries the current ETag; the Markdown and HTML outputs ignore If-None-Match.
{ "code": "unauthorized", "message": "Export ticket is required."}{ "message": "You do not have access to this node.", "code": "forbidden"}With output=html, a ticket that is unknown, expired or already used:
{ "code": "forbidden", "message": "Export ticket is invalid or expired."}| 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": "Document not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Document not found | No document content exists for this node, or the node type does not support documents | Create document content with client.notes.document.set() first |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
PUT /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document
Section titled “PUT /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document”Creates a new document or fully replaces an existing document for a node.
Document content shape
Section titled “Document content shape”The content field is a block map. Each block’s id repeats its map key; parentId is the document’s node id for a top-level block; index is a sibling sort key (a0, a1, …); content is an array of inline text leaves; attrs holds optional block attributes. The service rejects block ids placed inside attrs, top-level content arrays, or a wrapper with type: "doc".
| Name | Required | Type | Description |
|---|---|---|---|
content.blocks.{blockId}.id | Yes | string | Block id; matches its key {blockId} in content.blocks |
content.blocks.{blockId}.type | Yes | string | Block type, for example paragraph, heading1, heading2, heading3, codeBlock, horizontalRule, blockquote, bulletList, orderedList, listItem, taskList, taskItem, table, drawing |
content.blocks.{blockId}.parentId | Yes | string | Containing node id (for top-level blocks) or containing block id (for nested blocks) |
content.blocks.{blockId}.index | Yes | string | Sort key ordering siblings |
content.blocks.{blockId}.content | No | array | Inline content. Each item has type (text), text, and optional marks |
content.blocks.{blockId}.attrs | No | object | Optional block attributes |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
If-Match | header | string | No | Optional precondition (RFC 9110): write only if the document is still at one of these ETags, as returned in the ETag header of a document read or write (a quoted tag, or a comma-separated list of them), or * for “the document exists”. Otherwise the write is refused with 412 version_conflict and nothing changes: read the document again and retry. Without it the write is unconditional: it merges into, or replaces, whatever is stored (last writer wins). |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
content | Yes | object | Rich-text document content (block map) |
curl -X PUT "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/document" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "content": { "type": "rich_text", "blocks": { "b_title": { "id": "b_title", "type": "heading1", "parentId": "node_8f3a2b", "index": "a0", "content": [ { "type": "text", "text": "Welcome to the project" } ] }, "b_intro": { "id": "b_intro", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a1", "content": [ { "type": "text", "text": "Read the " }, { "type": "text", "text": "onboarding checklist", "marks": [{ "type": "bold" }] }, { "type": "text", "text": " before your first standup." } ] } } } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.set('nb_abc123', 'node_8f3a2b', { content: { type: 'rich_text', blocks: { b_title: { id: 'b_title', type: 'heading1', parentId: 'node_8f3a2b', index: 'a0', content: [{ type: 'text', text: 'Welcome to the project' }], }, b_intro: { id: 'b_intro', type: 'paragraph', parentId: 'node_8f3a2b', index: 'a1', content: [ { type: 'text', text: 'Read the ' }, { type: 'text', text: 'onboarding checklist', marks: [{ type: 'bold' }] }, { type: 'text', text: ' before your first standup.' }, ], }, }, },});Response
Section titled “Response”{ "id": "node_8f3a2b", "content": { "type": "rich_text", "blocks": { "b_title": { "id": "b_title", "type": "heading1", "parentId": "node_8f3a2b", "index": "a0", "content": [ { "type": "text", "text": "Welcome to the project" } ] }, "b_intro": { "id": "b_intro", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a1", "content": [ { "type": "text", "text": "Read the " }, { "type": "text", "text": "onboarding checklist", "marks": [{ "type": "bold" }] }, { "type": "text", "text": " before your first standup." } ] } } }, "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1", "updatedAt": "2026-09-16T11:30:00.000Z", "updatedBy": "user_owner_1"}{ "message": "Node type does not support documents.", "code": "bad_request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Unsupported node type | This node type does not support document content | Only page, channel, and similar node types support documents |
{ "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 |
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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
The If-Match precondition failed: the document is not at any of the given ETags, or does not exist. Nothing was written.
{ "message": "The document changed since the version named by If-Match (or does not exist). Read it again and retry.", "code": "version_conflict"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
version_conflict | Document changed | The If-Match precondition failed: the document is not at any of the given ETags (another write landed since it was read), or it does not exist. Nothing was written | Read the document again, reapply the change on it and retry with the new ETag |
{ "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 |
PATCH /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document
Section titled “PATCH /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document”Merges content into an existing document. Top-level keys replace the stored ones; blocks (a map by block id, or a list of blocks with ids) merges by block id: a sent block replaces the stored block with that id, and every other stored block is kept. Removing blocks takes a PUT.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
If-Match | header | string | No | Optional precondition (RFC 9110): write only if the document is still at one of these ETags, as returned in the ETag header of a document read or write (a quoted tag, or a comma-separated list of them), or * for “the document exists”. Otherwise the write is refused with 412 version_conflict and nothing changes: read the document again and retry. Without it the write is unconditional: it merges into, or replaces, whatever is stored (last writer wins). |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
content | Yes | object | Partial rich-text document content to merge (a blocks map or list of blocks with ids) |
curl -X PATCH "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/document" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "content": { "blocks": { "b_intro": { "id": "b_intro", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a1", "content": [ { "type": "text", "text": "Read the onboarding checklist today." } ] } } } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.update('nb_abc123', 'node_8f3a2b', { content: { blocks: { b_intro: { id: 'b_intro', type: 'paragraph', parentId: 'node_8f3a2b', index: 'a1', content: [{ type: 'text', text: 'Read the onboarding checklist today.' }], }, }, },});Response
Section titled “Response”{ "id": "node_8f3a2b", "content": { "type": "rich_text", "blocks": { "b_welcome": { "id": "b_welcome", "type": "heading1", "parentId": "node_8f3a2b", "index": "a0", "content": [ { "type": "text", "text": "Welcome to the project" } ] }, "b_intro": { "id": "b_intro", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a1", "content": [ { "type": "text", "text": "Read the onboarding checklist today." } ] } } }, "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1", "updatedAt": "2026-09-16T12:00:00.000Z", "updatedBy": "user_owner_1"}{ "message": "Node type does not support documents.", "code": "bad_request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Unsupported node type | This node type does not support document content | Only page, channel, and similar node types support documents |
{ "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 |
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": "Document not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Document not found | No document exists for this node, so create it with client.notes.document.set() first | Use client.notes.document.set() to create the document before patching |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
The If-Match precondition failed: the document is not at any of the given ETags, or does not exist. Nothing was written.
{ "message": "The document changed since the version named by If-Match (or does not exist). Read it again and retry.", "code": "version_conflict"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
version_conflict | Document changed | The If-Match precondition failed: the document is not at any of the given ETags (another write landed since it was read), or it does not exist. Nothing was written | Read the document again, reapply the change on it and retry with the new ETag |
{ "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 |
POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document/append
Section titled “POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document/append”Appends one or more blocks to the END of a node’s rich-text document. The server assigns each block id, parentId, and index; client-supplied id, parentId, index, or attrs.id are rejected. Pass an X-Idempotency-Key header to make retries safe.
The body is a union of two forms. Provide exactly one.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
X-Idempotency-Key | header | string | No | Optional idempotency key (max 256 chars). Reusing the same key with an identical request body and node replays the original response; reusing it with a different body or node returns 409 |
If-Match | header | string | No | Optional precondition (RFC 9110): write only if the document is still at one of these ETags, as returned in the ETag header of a document read or write (a quoted tag, or a comma-separated list of them), or * for “the document exists”. Otherwise the write is refused with 412 version_conflict and nothing changes: read the document again and retry. Without it the write is unconditional: it merges into, or replaces, whatever is stored (last writer wins). |
Request body, form A: plain text
Section titled “Request body, form A: plain text”Use this when you want to append a single block derived from raw text.
| Name | Required | Type | Description |
|---|---|---|---|
text | Yes | string | Block content. Newlines are preserved as a single literal block |
type | No | string | Block type. One of paragraph, heading1, heading2, heading3, codeBlock. Default paragraph |
attrs | No | object | null | Optional block attributes |
Request body, form B: structured blocks
Section titled “Request body, form B: structured blocks”Use this when you want to append one or more structured blocks (with marks, headings, horizontal rules, and so on).
| Name | Required | Type | Description |
|---|---|---|---|
blocks | Yes | array | Flat array of 1 to 100 root-level blocks |
Each block in blocks has the following shape:
| Name | Required | Type | Description |
|---|---|---|---|
type | No | string | Block type. One of paragraph, heading1, heading2, heading3, codeBlock, horizontalRule. Default paragraph |
content | No | array | Inline content. Each item has type (text), text, and optional marks |
attrs | No | object | null | Optional block attributes |
curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/document/append" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: key_123" \ -d '{ "text": "All new joiners should pair with a buddy in week one.", "type": "paragraph" }'curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/document/append" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: key_124" \ -d '{ "blocks": [ { "type": "heading3", "content": [ { "type": "text", "text": "Buddy program" } ] }, { "type": "paragraph", "content": [ { "type": "text", "text": "Every new joiner is paired with an experienced teammate." } ] }, { "type": "horizontalRule" }, { "type": "paragraph", "content": [ { "type": "text", "text": "Questions? Ask in the team channel." } ] } ] }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.append( 'nb_abc123', 'node_8f3a2b', { text: 'All new joiners should pair with a buddy in week one.', type: 'paragraph' }, { XIdempotencyKey: 'key_123' },);import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.append( 'nb_abc123', 'node_8f3a2b', { blocks: [ { type: 'heading3', content: [{ type: 'text', text: 'Buddy program' }], }, { type: 'paragraph', content: [{ type: 'text', text: 'Every new joiner is paired with an experienced teammate.' }], }, { type: 'horizontalRule' }, { type: 'paragraph', content: [{ type: 'text', text: 'Questions? Ask in the team channel.' }], }, ], }, { XIdempotencyKey: 'key_124' },);Response
Section titled “Response”{ "id": "node_8f3a2b", "content": { "type": "rich_text", "blocks": { "b_existing_1": { "id": "b_existing_1", "type": "heading1", "parentId": "node_8f3a2b", "index": "a0", "content": [ { "type": "text", "text": "Welcome to the project" } ] }, "b_existing_2": { "id": "b_existing_2", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a1", "content": [ { "type": "text", "text": "This page outlines our onboarding process." } ] }, "b_server_001": { "id": "b_server_001", "type": "heading3", "parentId": "node_8f3a2b", "index": "a2", "content": [ { "type": "text", "text": "Buddy program" } ] }, "b_server_002": { "id": "b_server_002", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a3", "content": [ { "type": "text", "text": "Every new joiner is paired with an experienced teammate." } ] }, "b_server_003": { "id": "b_server_003", "type": "horizontalRule", "parentId": "node_8f3a2b", "index": "a4" }, "b_server_004": { "id": "b_server_004", "type": "paragraph", "parentId": "node_8f3a2b", "index": "a5", "content": [ { "type": "text", "text": "Questions? Ask in the team channel." } ] } } }, "createdAt": "2026-09-12T10:14:22.000Z", "createdBy": "user_owner_1", "updatedAt": "2026-09-16T12:30:00.000Z", "updatedBy": "user_owner_1", "appendedBlockIds": ["b_server_001", "b_server_002", "b_server_003", "b_server_004"]}{ "message": "This node type does not support documents.", "code": "bad_request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Invalid append request | The request body is invalid: provide exactly one of text or blocks, a non-empty text, an allowed block type, no server-managed fields (id/parentId/index/attrs.id), at most 100 blocks, and content under the size limit. Also returned when the node type does not support documents | Send a valid append payload to a page (or other document-bearing) node |
{ "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 |
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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
{ "message": "Idempotency key already used with a different request.", "code": "bad_request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Idempotency key conflict | The X-Idempotency-Key was already used with a different request body or node | Use a fresh X-Idempotency-Key for a different append, or resend the identical request to replay |
The If-Match precondition failed: the document is not at any of the given ETags, or does not exist. Nothing was written.
{ "message": "The document changed since the version named by If-Match (or does not exist). Read it again and retry.", "code": "version_conflict"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
version_conflict | Document changed | The If-Match precondition failed: the document is not at any of the given ETags (another write landed since it was read), or it does not exist. Nothing was written | Read the document again, reapply the change on it and retry with the new ETag |
{ "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 |
POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/export-ticket
Section titled “POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/export-ticket”Creates a short-lived export ticket used to fetch the document as static HTML. Pass the ticket back via the ticket query parameter on GET .../document?output=html.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
output | No | string | Output format. One of html. Default html |
includeComments | No | string | Whether to include comments. One of none, appendix. Default none |
includeBackground | No | boolean | Whether to embed the page background in the HTML. Default true |
themeMode | No | string | One of light, dark. Default dark |
themeId | No | string | null | Optional theme identifier (max 64 chars) |
themeVariables | No | object | Optional theme variable overrides (string values) |
fileName | No | string | Optional filename hint for the downloaded file (max 128 chars) |
curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/export-ticket" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "output": "html", "includeComments": "appendix", "themeMode": "light", "fileName": "Onboarding.html" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.createExportTicket('nb_abc123', 'node_8f3a2b', { output: 'html', includeComments: 'appendix', themeMode: 'light', fileName: 'Onboarding.html',});Response
Section titled “Response”{ "ticket": "tkt_8a4b2d9c", "expiresAt": "2026-09-16T13:00:00.000Z", "usesRemaining": 1}{ "code": "notebook_no_access", "message": "You do not have access to this notebook."}| Error Code | Title | Description | Resolution |
|---|---|---|---|
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 |
{ "code": "notebook_not_found", "message": "Notebook not found."}| Error Code | Title | Description | Resolution |
|---|---|---|---|
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/blocks/{blockId}/svg
Section titled “GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/blocks/{blockId}/svg”Renders a drawing block as an SVG image. Supports an optional background color and scale factor. Only drawing blocks can be exported; any other block type is a 400.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
blockId | path | string | Yes | Identifier of the drawing block |
bg | query | string | No | Background color, for example #ffffff or transparent |
scale | query | number | No | Scale factor applied to the rendered SVG |
curl -X GET "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/blocks/block_d12/svg?bg=transparent&scale=2" \ -H "Authorization: Bearer <token>" \ -o drawing.svgimport { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.document.exportBlock('nb_abc123', 'node_8f3a2b', 'block_d12', { bg: 'transparent', scale: 2 });Response
Section titled “Response”Content-Type: image/svg+xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" width="600" height="400"> <rect x="0" y="0" width="600" height="400" fill="#ffffff"/> <path d="M 50 200 Q 150 50 300 200 T 550 200" stroke="#1f2937" stroke-width="3" fill="none"/> <circle cx="300" cy="200" r="40" fill="#3b82f6"/> <text x="300" y="350" text-anchor="middle" font-family="sans-serif" font-size="18" fill="#1f2937">Architecture sketch</text></svg>| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Not a drawing block | The specified block is not a drawing canvas block | SVG export is only available for drawing canvas blocks |
| 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 |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Block not found | The specified block does not exist in the document, or the drawing has no SVG data | Read the node’s document to find valid block IDs and verify the block is a drawing |
notebook_not_found | Notebook not found | No notebook exists with the provided ID | Verify the notebook ID in the URL |
Interactions
Section titled “Interactions”POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/interactions/opened
Section titled “POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/interactions/opened”Records that the current user has opened the node. Tracks first and last opened timestamps.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
openedAt | No | string | Optional ISO 8601 timestamp at which the open occurred |
curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/interactions/opened" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{}'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.markOpened('nb_abc123', 'node_8f3a2b', {});Response
Section titled “Response”{ "nodeId": "node_8f3a2b", "collaboratorId": "user_owner_1", "firstSeenAt": "2026-09-12T10:14:00.000Z", "lastSeenAt": "2026-09-15T08:01:50.000Z", "firstOpenedAt": "2026-09-15T08:01:55.000Z", "lastOpenedAt": "2026-09-16T13:00:00.000Z"}{ "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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
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 |
POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/interactions/seen
Section titled “POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/interactions/seen”Records that the current user has seen the node. Tracks first and last seen timestamps.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | Identifier of the notebook |
nodeId | path | string | Yes | Identifier of the node |
Request body
Section titled “Request body”| Name | Required | Type | Description |
|---|---|---|---|
seenAt | No | string | Optional ISO 8601 timestamp at which the seen event occurred |
curl -X POST "https://{projectId}-{containerId}-notes-1.{server}.containers.hoody.com/api/v1/notes/notebooks/nb_abc123/nodes/node_8f3a2b/interactions/seen" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{}'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: '<the operation Base URL>', token: process.env.HOODY_TOKEN });
await client.notes.nodes.markSeen('nb_abc123', 'node_8f3a2b', {});Response
Section titled “Response”{ "nodeId": "node_8f3a2b", "collaboratorId": "user_owner_1", "firstSeenAt": "2026-09-12T10:14:00.000Z", "lastSeenAt": "2026-09-16T13:00:00.000Z", "firstOpenedAt": "2026-09-15T08:01:55.000Z", "lastOpenedAt": "2026-09-15T08:02:11.000Z"}{ "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": "Node not found.", "code": "not_found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Node not found | No node exists with the provided ID in this notebook | Verify node ID using client.notes.nodes.list() or client.notes.nodes.listChildren() |
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 |