Documentation Index
Fetch the complete documentation index at: https://docs.velt.dev/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Velt Node SDK exposes two independent backends:
| Backend | Namespace | Use case |
|---|
| Self-hosting | sdk.selfHosting.* | Store Velt data in your own MongoDB + AWS S3 |
| REST API | sdk.api.* | Call Velt’s REST APIs directly — no database required |
Self-hosting backend (sdk.selfHosting.*) simplifies backend implementation by 90%. Instead of writing custom database queries and storage logic, you:
- Pass your DB and storage configs to the SDK
- Call the relevant SDK method with the raw request payload
- Return the resulting response directly to the client
REST API backend (sdk.api.*) provides feature parity with the Velt Python SDK. 17 services, fully-typed TypeScript request objects, and raw Velt API responses. No database or AWS configuration needed.
Installation
npm install @veltdev/node
For self-hosting, also install the optional peer dependencies you plan to use:
npm install mongodb # required for self-hosting backend
npm install @aws-sdk/client-s3 # required only if using S3 for attachments
Requirements
- Node.js 18+
- TypeScript 5.x (optional — JavaScript is fully supported)
- MongoDB 6+ (Percona Server or MongoDB Atlas) for self-hosting
mongodb ^6 and @aws-sdk/client-s3 ^3 as optional peer dependencies
Quick Start
Initialize the SDK
Self-hosting initialization (MongoDB + optional AWS):
import { VeltSDK } from '@veltdev/node';
const sdk = VeltSDK.initialize({
database: {
host: 'localhost:27017',
username: 'your-username',
password: 'your-password',
auth_database: 'admin',
database_name: 'velt-integration',
},
apiKey: 'YOUR_VELT_API_KEY',
authToken: 'YOUR_VELT_AUTH_TOKEN'
});
REST API-only initialization (no database needed):
import { VeltSDK } from '@veltdev/node';
const sdk = VeltSDK.initialize({
apiKey: 'YOUR_VELT_API_KEY',
authToken: 'YOUR_VELT_AUTH_TOKEN'
});
// All sdk.api.* services are now available
const result = await sdk.api.organizations.getOrganizations({ organizationIds: ['org-123'] });
The database section is optional when using only sdk.api.*. Set VELT_API_KEY and VELT_AUTH_TOKEN environment variables as an alternative to passing credentials in the config object.
Shutdown
Call await sdk.close() when your process exits to release the database connection pool.
Configuration
Environment Variables
| Variable | Config key equivalent | Purpose |
|---|
VELT_API_KEY | apiKey | Velt API key for authenticating REST API calls |
VELT_AUTH_TOKEN | authToken | Velt auth token for authenticating REST API calls |
VELT_WORKSPACE_ID | — | Default workspace ID for workspace-scoped operations |
VELT_WORKSPACE_AUTH_TOKEN | — | Auth token scoped to a specific workspace |
AWS_ACCESS_KEY_ID | — | AWS access key for S3 attachments |
AWS_SECRET_ACCESS_KEY | — | AWS secret key for S3 attachments |
AWS_REGION | — | AWS region for S3 |
AWS_S3_BUCKET_NAME | — | S3 bucket name for attachments |
AWS_S3_ENDPOINT_URL | — | Custom S3 endpoint (e.g., for MinIO) |
Self-Hosting Configuration
Database
AWS (Attachments)
Complete Example
Configure MongoDB connection for storing comments, reactions, and user data.const sdk = VeltSDK.initialize({
database: {
// Option 1: Connection string (recommended for MongoDB Atlas)
// Overrides host/username/password if provided
connection_string: 'mongodb+srv://user:pass@cluster.mongodb.net/velt-db',
// Option 2: Individual components
// host: 'localhost:27017',
// username: 'your-username',
// password: 'your-password',
// auth_database: 'admin',
// database_name: 'velt-db',
// Optional fields:
// type: 'mongodb', // defaults to 'mongodb'
// use_srv: true, // use mongodb+srv:// (auto-detected for *.mongodb.net hosts)
}
});
Configure AWS S3 for storing file attachments. Alternatively, set the AWS environment variables listed above.const sdk = VeltSDK.initialize({
database: { connection_string: 'mongodb+srv://...' },
// AWS credentials can also be provided via environment variables
apiKey: 'YOUR_VELT_API_KEY',
authToken: 'YOUR_VELT_AUTH_TOKEN'
});
Full configuration with database and credentials.import { VeltSDK } from '@veltdev/node';
const sdk = VeltSDK.initialize({
database: {
connection_string: 'mongodb+srv://user:pass@cluster.mongodb.net/velt-db',
},
apiKey: 'YOUR_VELT_API_KEY',
authToken: 'YOUR_VELT_AUTH_TOKEN'
});
// Graceful shutdown
process.on('SIGTERM', async () => {
await sdk.close();
process.exit(0);
});
Self-Hosting Backend
Each self-hosting service is loaded asynchronously on first access via await sdk.selfHosting.getXxx(). The service is cached after the first call. The token service is the exception — it is available as a direct synchronous property via sdk.selfHosting.token.
Access via await sdk.selfHosting.getComments().
const commentsService = await sdk.selfHosting.getComments();
const result = await commentsService.getComments({
organizationId: 'org-123',
documentIds: ['doc-1'],
});
Response
{
success: true,
statusCode: 200,
data: { /* comment annotations keyed by annotationId */ }
}
const commentsService = await sdk.selfHosting.getComments();
const result = await commentsService.saveComments({
metadata: { organizationId: 'org-123', documentId: 'doc-1' },
commentAnnotation: {
'annotation-1': {
annotationId: 'annotation-1',
comments: { '123456': { commentId: '123456', commentText: 'Hello' } },
metadata: {},
},
},
});
Response
{ success: true, statusCode: 200, data: { saved: true } }
const commentsService = await sdk.selfHosting.getComments();
const result = await commentsService.deleteComment({
commentAnnotationId: 'annotation-1',
metadata: { organizationId: 'org-123' },
});
Response
{ success: true, statusCode: 200, data: { deleted: true } }
Reactions
Access via await sdk.selfHosting.getReactions().
getReactions
const reactionsService = await sdk.selfHosting.getReactions();
const result = await reactionsService.getReactions({
organizationId: 'org-123',
documentIds: ['doc-1'],
});
Response
{ success: true, statusCode: 200, data: { /* reaction annotations */ } }
saveReactions
const reactionsService = await sdk.selfHosting.getReactions();
const result = await reactionsService.saveReactions({
metadata: { organizationId: 'org-123', documentId: 'doc-1' },
reactionAnnotation: {
'reaction-1': { annotationId: 'reaction-1', icon: 'thumbsup', metadata: {} },
},
});
Response
{ success: true, statusCode: 200, data: { saved: true } }
deleteReaction
const reactionsService = await sdk.selfHosting.getReactions();
const result = await reactionsService.deleteReaction({
reactionAnnotationId: 'reaction-1',
metadata: { organizationId: 'org-123' },
});
Response
{ success: true, statusCode: 200, data: { deleted: true } }
Attachments
Access via await sdk.selfHosting.getAttachments().
getAttachment
- Fetches an attachment record by organization and attachment ID.
- Params: positional —
organizationId (string), attachmentId (number)
- Returns: VeltSelfHostingResponse
const attachmentsService = await sdk.selfHosting.getAttachments();
const result = await attachmentsService.getAttachment('org-123', 12345);
Response
{
success: true,
statusCode: 200,
data: {
attachmentId: 12345,
name: 'document.pdf',
mimeType: 'application/pdf',
size: 1024,
url: 'https://s3.amazonaws.com/...'
}
}
saveAttachment
const attachmentsService = await sdk.selfHosting.getAttachments();
const result = await attachmentsService.saveAttachment(
{
metadata: { organizationId: 'org-123', documentId: 'doc-1' },
attachment: {
attachmentId: 12345,
name: 'document.pdf',
mimeType: 'application/pdf',
size: 1024,
},
},
fileBuffer, // optional Buffer for S3 upload
'document.pdf', // optional
'application/pdf' // optional
);
Response
{ success: true, statusCode: 200, data: { saved: true, attachmentId: 12345 } }
deleteAttachment
const attachmentsService = await sdk.selfHosting.getAttachments();
const result = await attachmentsService.deleteAttachment({
attachmentId: 12345,
metadata: { organizationId: 'org-123' },
});
Response
{ success: true, statusCode: 200, data: { deleted: true } }
Users
Access via await sdk.selfHosting.getUsers().
getUsers
const usersService = await sdk.selfHosting.getUsers();
const result = await usersService.getUsers({
organizationId: 'org-123',
userIds: ['user-1'],
});
Response
{
success: true,
statusCode: 200,
data: [{ userId: 'user-1', name: 'John Doe', email: 'john@example.com' }]
}
Recorder
Access via await sdk.selfHosting.getRecorder().
getRecorderAnnotations
const recorderService = await sdk.selfHosting.getRecorder();
const result = await recorderService.getRecorderAnnotations({
organizationId: 'org-123',
documentIds: ['doc-1'],
});
Response
{ success: true, statusCode: 200, data: { /* recorder annotations */ } }
saveRecorderAnnotation
const recorderService = await sdk.selfHosting.getRecorder();
const result = await recorderService.saveRecorderAnnotation({
metadata: { organizationId: 'org-123', documentId: 'doc-1' },
recorderAnnotation: { annotationId: 'rec-1', metadata: {} },
});
Response
{ success: true, statusCode: 200, data: { saved: true } }
deleteRecorderAnnotation
const recorderService = await sdk.selfHosting.getRecorder();
const result = await recorderService.deleteRecorderAnnotation({
recorderAnnotationId: 'rec-1',
metadata: { organizationId: 'org-123' },
});
Response
{ success: true, statusCode: 200, data: { deleted: true } }
Notifications
Access via await sdk.selfHosting.getNotifications().
getNotifications
const notificationsService = await sdk.selfHosting.getNotifications();
const result = await notificationsService.getNotifications({
organizationId: 'org-123',
userId: 'user-1',
});
Response
{ success: true, statusCode: 200, data: [/* notifications */] }
saveNotifications
const notificationsService = await sdk.selfHosting.getNotifications();
await notificationsService.saveNotifications({
metadata: { organizationId: 'org-123', documentId: 'doc-1' },
notifications: [{ id: 'n-1', actionUser: { userId: 'user-1' }, displayBodyMessage: 'Hello' }],
});
Response
{ success: true, statusCode: 200, data: { saved: true } }
deleteNotification
const notificationsService = await sdk.selfHosting.getNotifications();
await notificationsService.deleteNotification({
notificationId: 'n-1',
metadata: { organizationId: 'org-123', userId: 'user-1' },
});
Response
{ success: true, statusCode: 200, data: { deleted: true } }
Activities
Access via await sdk.selfHosting.getActivities().
getActivities
const activitiesService = await sdk.selfHosting.getActivities();
const result = await activitiesService.getActivities({
organizationId: 'org-123',
documentId: 'doc-1',
});
Response
{ success: true, statusCode: 200, data: [/* activities */] }
saveActivities
const activitiesService = await sdk.selfHosting.getActivities();
await activitiesService.saveActivities({
metadata: { organizationId: 'org-123', documentId: 'doc-1' },
activities: [{ id: 'activity-1', featureType: 'comment', actionType: 'comment.add' }],
});
Response
{ success: true, statusCode: 200, data: { saved: true } }
Token
Access via the synchronous sdk.selfHosting.token property (no await).
getToken
- Generates a Velt auth token for a user.
- Params: positional —
organizationId (string), userId (string), email (string, optional), isAdmin (boolean, optional)
- Returns: VeltSelfHostingResponse
Note: getToken takes positional arguments — not a request object.
const tokenResult = await sdk.selfHosting.token.getToken(
'org-123',
'user-1',
'john@example.com',
false
);
const token = (tokenResult.data as { token: string }).token;
Response
{ success: true, statusCode: 200, data: { token: 'eyJhbGciOiJIUzI1NiIs...' } }
REST API Backend
The sdk.api.* namespace provides 17 services covering all Velt REST API operations. No database or AWS configuration is required — only apiKey and authToken.
Every sdk.api.* method requires an organizationId in its request payload. Velt enforces data isolation per-organization server-side.
Organizations
Namespace: sdk.api.organizations
addOrganizations
await sdk.api.organizations.addOrganizations({
organizations: [{ organizationId: 'org-123', organizationName: 'My Organization' }],
});
Response
{
result: {
status: 'success',
message: 'Organization(s) added successfully.',
data: {
'org-123': { success: true, id: '02cf91e5...', message: 'Added Successfully' }
}
}
}
getOrganizations
await sdk.api.organizations.getOrganizations({
organizationIds: ['org-123'],
pageSize: 10,
pageToken: 'next-page-token',
});
Response
{
result: {
status: 'success',
message: 'Organization(s) retrieved successfully.',
data: [
{ id: 'org-123', organizationName: 'Your Organization Name', disabled: false }
],
nextPageToken: 'pageToken'
}
}
updateOrganizations
await sdk.api.organizations.updateOrganizations({
organizations: [{ organizationId: 'org-123', organizationName: 'Updated Name' }],
});
Response
{ result: { status: 'success', message: 'Organization(s) updated successfully.', data: {} } }
deleteOrganizations
await sdk.api.organizations.deleteOrganizations({ organizationIds: ['org-123'] });
Response
{ result: { status: 'success', message: 'Organization(s) deleted successfully.', data: {} } }
updateOrganizationDisableState
await sdk.api.organizations.updateOrganizationDisableState({
organizationIds: ['org-123'],
disabled: true,
});
Response
{ result: { status: 'success', message: 'Organization(s) disable state updated.', data: {} } }
Folders
Namespace: sdk.api.folders
addFolder
await sdk.api.folders.addFolder({
organizationId: 'org-123',
folders: [{ folderId: 'folder-1', folderName: 'My Folder' }],
createOrganization: true,
});
Response
{ result: { status: 'success', message: 'Folder(s) added successfully.', data: {} } }
getFolders
await sdk.api.folders.getFolders({
organizationId: 'org-123',
folderId: 'folder-1',
maxDepth: 3,
});
Response
{
result: {
status: 'success',
message: 'Folders retrieved successfully.',
data: [
{
folderId: 'folder-1',
folderName: 'Folder 1',
organizationId: 'org-123',
parentFolderId: 'root',
createdAt: 1738695615706,
lastUpdated: 1738696287859
}
]
}
}
updateFolder
await sdk.api.folders.updateFolder({
organizationId: 'org-123',
folders: [{ folderId: 'folder-1', folderName: 'Renamed' }],
});
Response
{ result: { status: 'success', message: 'Folder(s) updated successfully.', data: {} } }
deleteFolder
await sdk.api.folders.deleteFolder({ organizationId: 'org-123', folderId: 'folder-1' });
Response
{ result: { status: 'success', message: 'Folder deleted successfully.', data: {} } }
updateFolderAccess
await sdk.api.folders.updateFolderAccess({
organizationId: 'org-123',
folderIds: ['folder-1'],
accessType: 'restricted',
});
Response
{ result: { status: 'success', message: 'Folder access updated successfully.', data: {} } }
Documents
Namespace: sdk.api.documents
addDocuments
await sdk.api.documents.addDocuments({
organizationId: 'org-123',
documents: [
{ documentId: 'doc-1', documentName: 'My Document' },
{ documentId: 'doc-2', documentName: 'Another Document' },
],
createOrganization: true,
folderId: 'folder-1',
createFolder: true,
});
Response
{
result: {
status: 'success',
message: 'Document(s) added successfully.',
data: {
'doc-1': { success: true, message: 'Added Successfully' },
'doc-2': { success: true, message: 'Added Successfully' }
}
}
}
getDocuments
await sdk.api.documents.getDocuments({
organizationId: 'org-123',
documentIds: ['doc-1'],
folderId: 'folder-1',
pageSize: 10,
});
Response
{
result: {
status: 'success',
message: 'Document(s) retrieved successfully.',
data: [
{ documentName: 'yourDocumentName', disabled: false, accessType: 'public', id: 'yourDocumentId' }
],
pageToken: 'nextPageToken'
}
}
updateDocuments
await sdk.api.documents.updateDocuments({
organizationId: 'org-123',
documents: [{ documentId: 'doc-1', documentName: 'Renamed' }],
});
Response
{ result: { status: 'success', message: 'Document(s) updated successfully.', data: {} } }
deleteDocuments
await sdk.api.documents.deleteDocuments({
organizationId: 'org-123',
documentIds: ['doc-1', 'doc-2'],
});
Response
{ result: { status: 'success', message: 'Document(s) deleted successfully.', data: {} } }
moveDocuments
await sdk.api.documents.moveDocuments({
organizationId: 'org-123',
documentIds: ['doc-1', 'doc-2'],
folderId: 'target-folder-id',
});
Response
{ result: { status: 'success', message: 'Document(s) moved successfully.', data: {} } }
updateDocumentAccess
await sdk.api.documents.updateDocumentAccess({
organizationId: 'org-123',
documentIds: ['doc-1', 'doc-2'],
accessType: 'organizationPrivate',
});
Response
{ result: { status: 'success', message: 'Document access updated successfully.', data: {} } }
updateDocumentDisableState
await sdk.api.documents.updateDocumentDisableState({
organizationId: 'org-123',
documentIds: ['doc-1'],
disabled: true,
});
Response
{ result: { status: 'success', message: 'Document(s) disable state updated.', data: {} } }
migrateDocuments
Note: migrateDocuments is asynchronous and returns a migrationId. Poll completion with migrateDocumentsStatus.
await sdk.api.documents.migrateDocuments({
organizationId: 'org-123',
documentId: 'old-doc-id',
newDocumentId: 'new-doc-id',
});
Response
{
result: {
status: 'success',
message: 'Document migration started successfully.',
data: { migrationId: 'yourMigrationId' }
}
}
migrateDocumentsStatus
await sdk.api.documents.migrateDocumentsStatus({
organizationId: 'org-123',
migrationId: 'migration-1',
});
Response
{
result: {
status: 'success',
message: 'Migration status retrieved successfully.',
data: { migrationId: 'yourMigrationId', status: 'completed' }
}
}
Users
Namespace: sdk.api.users
addUsers
await sdk.api.users.addUsers({
organizationId: 'org-123',
users: [{ userId: 'user-1', name: 'John Doe', email: 'john@example.com', accessRole: 'editor' }],
createOrganization: true,
});
Response
{ result: { status: 'success', message: 'User(s) added successfully.', data: {} } }
getUsers
await sdk.api.users.getUsers({
organizationId: 'org-123',
userIds: ['user-1'],
documentId: 'doc-1',
pageSize: 100,
allDocuments: true,
groupByDocumentId: true,
});
Response
{
result: {
status: 'success',
message: 'User(s) retrieved successfully.',
data: [
{ email: 'userEmail@domain.com', name: 'userName', userId: 'yourUserId' }
],
nextPageToken: 'pageToken'
}
}
updateUsers
await sdk.api.users.updateUsers({
organizationId: 'org-123',
users: [{ userId: 'user-1', name: 'Jane Doe', accessRole: 'viewer' }],
});
Response
{ result: { status: 'success', message: 'User(s) updated successfully.', data: {} } }
deleteUsers
await sdk.api.users.deleteUsers({ organizationId: 'org-123', userIds: ['user-1'] });
Response
{ result: { status: 'success', message: 'User(s) deleted successfully.', data: {} } }
User Groups
Namespace: sdk.api.userGroups
addUserGroups
await sdk.api.userGroups.addUserGroups({
organizationId: 'org-123',
organizationUserGroups: [{ groupId: 'engineering', groupName: 'Engineering' }],
createOrganization: true,
});
Response
{ result: { status: 'success', message: 'User group(s) added successfully.', data: {} } }
addUsersToGroup
await sdk.api.userGroups.addUsersToGroup({
organizationId: 'org-123',
organizationUserGroupId: 'engineering',
userIds: ['user-1', 'user-2'],
});
Response
{ result: { status: 'success', message: 'Users added to group successfully.', data: {} } }
deleteUsersFromGroup
await sdk.api.userGroups.deleteUsersFromGroup({
organizationId: 'org-123',
organizationUserGroupId: 'engineering',
userIds: ['user-1'],
});
Response
{ result: { status: 'success', message: 'Users removed from group successfully.', data: {} } }
Notifications
Namespace: sdk.api.notifications
addNotifications
await sdk.api.notifications.addNotifications({
organizationId: 'org-123',
documentId: 'doc-1',
actionUser: { userId: 'user-1', name: 'John Doe', email: 'john@example.com' },
displayHeadlineMessageTemplate: '{actionUser} commented on your document',
displayBodyMessage: 'Check out the new comment',
notifyUsers: [{ userId: 'user-2', name: 'Jane Doe' }],
createOrganization: true,
createDocument: true,
});
Response
{ result: { status: 'success', message: 'Notification(s) added successfully.', data: {} } }
getNotifications
await sdk.api.notifications.getNotifications({
organizationId: 'org-123',
userId: 'user-2',
pageSize: 10,
order: 'desc',
});
Response
{
result: {
status: 'success',
message: 'Notification(s) retrieved successfully.',
data: [
{
id: 'notificationId',
notificationSource: 'custom',
actionUser: { userId: 'user-1', name: 'John Doe', email: 'john@example.com' },
displayBodyMessage: 'Check out the new comment',
displayHeadlineMessageTemplate: '{actionUser} commented on your document',
timestamp: 1722409519944
}
],
pageToken: 'nextPageToken'
}
}
updateNotifications
await sdk.api.notifications.updateNotifications({
organizationId: 'org-123',
userId: 'user-2',
notifications: [{ notificationId: 'n-1', read: true }],
});
Response
{ result: { status: 'success', message: 'Notification(s) updated successfully.', data: {} } }
deleteNotifications
await sdk.api.notifications.deleteNotifications({
organizationId: 'org-123',
userId: 'user-2',
notificationIds: ['n-1'],
});
Response
{ result: { status: 'success', message: 'Notification(s) deleted successfully.', data: {} } }
getNotificationConfig
await sdk.api.notifications.getNotificationConfig({
organizationId: 'org-123',
userId: 'user-1',
});
Response
{
result: {
status: 'success',
message: 'User config fetched successfully.',
data: [
{
config: { inbox: 'ALL', email: 'ALL' },
metadata: { organizationId: 'org-123', apiKey: 'API_KEY', documentId: 'doc-1', userId: 'user-1' }
}
]
}
}
setNotificationConfig
await sdk.api.notifications.setNotificationConfig({
organizationId: 'org-123',
userIds: ['user-1', 'user-2'],
config: { inbox: 'ALL', email: 'MINE', slack: 'NONE' },
});
Response
{ result: { status: 'success', message: 'User config set successfully.', data: {} } }
Namespace: sdk.api.commentAnnotations
await sdk.api.commentAnnotations.addCommentAnnotations({
organizationId: 'org-123',
documentId: 'doc-1',
commentAnnotations: [{
location: { id: 'section-1', locationName: 'Introduction' },
commentData: [{
commentText: 'This needs review',
commentHtml: '<p>This needs review</p>',
from: { userId: 'user-1', name: 'John Doe', email: 'john@example.com' },
}],
}],
});
Response
{ result: { status: 'success', message: 'Annotation(s) added successfully.', data: {} } }
await sdk.api.commentAnnotations.getCommentAnnotations({
organizationId: 'org-123',
documentId: 'doc-1',
statusIds: ['OPEN'],
pageSize: 10,
});
Response
{
result: {
status: 'success',
message: 'Annotations fetched successfully.',
data: [
{
type: 'comment',
comments: [
{
commentId: 123456,
commentText: 'This is a sample comment text.',
commentHtml: '<p>This is a sample comment text.</p>',
from: { userId: 'user123', name: 'John Doe', email: 'john.doe@example.com' },
createdAt: 1687344600000
}
],
status: { id: 'OPEN', name: 'Open', type: 'default' }
}
]
}
}
await sdk.api.commentAnnotations.getCommentAnnotationsCount({
organizationId: 'org-123',
documentIds: ['doc-1', 'doc-2'],
userId: 'user-1',
});
Response
{
result: {
status: 'success',
message: 'Comment count retrieved successfully.',
data: {
'doc-1': { total: 4, unread: 2 },
'doc-2': { total: 2, unread: 0 }
}
}
}
await sdk.api.commentAnnotations.updateCommentAnnotations({
organizationId: 'org-123',
documentId: 'doc-1',
annotationIds: ['annotation-id-1'],
updatedData: { status: { id: 'RESOLVED', name: 'Resolved', type: 'terminal' } },
});
Response
{ result: { status: 'success', message: 'Annotation(s) updated successfully.', data: {} } }
await sdk.api.commentAnnotations.deleteCommentAnnotations({
organizationId: 'org-123',
documentId: 'doc-1',
annotationIds: ['annotation-id-1'],
});
Response
{ result: { status: 'success', message: 'Annotation(s) deleted successfully.', data: {} } }
await sdk.api.commentAnnotations.addComments({
organizationId: 'org-123',
documentId: 'doc-1',
annotationId: 'annotation-id-1',
commentData: [{
commentText: 'I agree, let me fix this',
from: { userId: 'user-2', name: 'Jane Doe' },
}],
});
Response
{ result: { status: 'success', message: 'Comment(s) added successfully.', data: {} } }
await sdk.api.commentAnnotations.getComments({
organizationId: 'org-123',
documentId: 'doc-1',
annotationId: 'annotation-id-1',
userIds: ['user-1'],
});
Response
{
result: {
status: 'success',
message: 'Comments(s) retrieved successfully.',
data: [
{
commentId: 153783,
commentText: 'Sample Comment Text',
commentHtml: '<div>Hello Updated 2</div>',
from: { userId: 'yourUserId', name: 'User Name', email: 'user@example.com' },
lastUpdated: '2024-06-20T09:53:42.258Z',
status: 'added',
type: 'text'
}
]
}
}
await sdk.api.commentAnnotations.updateComments({
organizationId: 'org-123',
documentId: 'doc-1',
annotationId: 'annotation-id-1',
commentIds: [123456],
updatedData: { commentText: 'Updated text', commentHtml: '<p>Updated text</p>' },
});
Response
{ result: { status: 'success', message: 'Comment(s) updated successfully.', data: {} } }
await sdk.api.commentAnnotations.deleteComments({
organizationId: 'org-123',
documentId: 'doc-1',
annotationId: 'annotation-id-1',
commentIds: [123456],
});
Response
{ result: { status: 'success', message: 'Comment(s) deleted successfully.', data: {} } }
Activities
Namespace: sdk.api.activities
addActivities
await sdk.api.activities.addActivities({
organizationId: 'org-123',
documentId: 'doc-456',
activities: [{
featureType: 'comment',
actionType: 'comment.add',
actionUser: { userId: 'user-1', name: 'John Doe', email: 'john@example.com' },
displayMessageTemplate: '{{user}} added a comment',
}],
});
Response
{ result: { status: 'success', message: 'Activity(s) added successfully.', data: {} } }
getActivities
await sdk.api.activities.getActivities({
organizationId: 'org-123',
documentId: 'doc-456',
featureTypes: ['comment'],
order: 'desc',
pageSize: 50,
});
Response
{
result: {
status: 'success',
message: 'Activity(s) retrieved successfully.',
data: [
{
id: 'activity-001',
featureType: 'comment',
actionType: 'comment.add',
actionUser: { userId: 'user-1', email: 'user@example.com', name: 'User Name' },
targetEntityId: 'annotation-789',
displayMessageTemplate: '{{user}} added a comment',
metadata: { apiKey: 'yourApiKey', documentId: 'doc-456', organizationId: 'org-123' },
timestamp: 1722409519944
}
],
pageToken: 'nextPageToken'
}
}
updateActivities
await sdk.api.activities.updateActivities({
organizationId: 'org-123',
activities: [{ id: 'activity-001', displayMessageTemplate: '{{user}} updated the comment' }],
});
Response
{ result: { status: 'success', message: 'Activity(s) updated successfully.', data: {} } }
deleteActivities
await sdk.api.activities.deleteActivities({
organizationId: 'org-123',
documentId: 'doc-456',
});
Response
{ result: { status: 'success', message: 'Activity(s) deleted successfully.', data: {} } }
Access Control
Namespace: sdk.api.accessControl
addPermissions
await sdk.api.accessControl.addPermissions({
user: { userId: 'user-1' },
permissions: {
resources: [
{ type: 'organization', id: 'org-123', accessRole: 'editor' },
{ type: 'document', id: 'doc-1', organizationId: 'org-123', accessRole: 'viewer', expiresAt: 1728902400 },
],
},
});
Response
{ result: { status: 'success', message: 'Permissions added successfully.', data: {} } }
getPermissions
await sdk.api.accessControl.getPermissions({
organizationId: 'org-123',
userIds: ['user-1'],
documentIds: ['doc-1'],
});
Response
{
result: {
status: 'success',
message: 'User permissions retrieved successfully.',
data: {
'user-1': {
documents: { 'doc-1': { accessRole: 'viewer', accessType: 'restricted' } },
organization: { 'org-123': { accessRole: 'editor' } }
}
}
}
}
removePermissions
await sdk.api.accessControl.removePermissions({
userId: 'user-1',
permissions: {
resources: [
{ type: 'organization', id: 'org-123' },
{ type: 'document', id: 'doc-1', organizationId: 'org-123' },
],
},
});
Response
{ result: { status: 'success', message: 'Permissions removed successfully.', data: {} } }
generateSignature
await sdk.api.accessControl.generateSignature({
permissions: [{
userId: 'user-1',
resourceId: 'doc-1',
type: 'document',
hasAccess: true,
accessRole: 'viewer',
}],
});
Response
{
result: {
status: 'success',
message: 'Signature generated successfully.',
data: { signature: 'a1b2c3d4e5f6...' }
}
}
generateToken
await sdk.api.accessControl.generateToken({
userId: 'user-1',
userProperties: { name: 'John Doe', email: 'john@example.com', isAdmin: false },
permissions: {
resources: [
{ type: 'organization', id: 'org-123', accessRole: 'viewer' },
{ type: 'document', id: 'doc-1', organizationId: 'org-123', accessRole: 'editor' },
],
},
});
Response
{
result: {
status: 'success',
message: 'Token generated successfully.',
data: { token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' }
}
}
CRDT
Namespace: sdk.api.crdt
Supports text, map, array, and xml CRDT data types.
addCrdtData
await sdk.api.crdt.addCrdtData({
organizationId: 'org-123',
documentId: 'doc-1',
editorId: 'my-collab-note',
data: 'Hello, collaborative world!',
type: 'text',
});
Response
{ result: { status: 'success', message: 'CRDT data added successfully.', data: {} } }
getCrdtData
await sdk.api.crdt.getCrdtData({
organizationId: 'org-123',
documentId: 'doc-1',
editorId: 'my-collab-note',
});
Response
{
result: {
status: 'success',
message: 'CRDT data retrieved successfully.',
data: [
{
data: 'Hello, collaborative world!',
id: 'my-collab-note',
lastUpdate: '2025-01-20T10:30:00.000Z',
lastUpdatedBy: 'user-123',
sessionId: 'session-abc-456'
}
]
}
}
updateCrdtData
await sdk.api.crdt.updateCrdtData({
organizationId: 'org-123',
documentId: 'doc-1',
editorId: 'my-collab-note',
data: 'Updated collaborative content!',
type: 'text',
});
Response
{ result: { status: 'success', message: 'CRDT data updated successfully.', data: {} } }
Presence
Namespace: sdk.api.presence
addPresence
await sdk.api.presence.addPresence({
organizationId: 'org-123',
documentId: 'doc-456',
users: [
{ userId: 'user-1', name: 'John Doe', email: 'john@example.com', status: 'online' },
{ userId: 'user-2', name: 'Jane Doe', status: 'away' },
],
});
Response
{ result: { status: 'success', message: 'Presence added successfully.', data: {} } }
updatePresence
await sdk.api.presence.updatePresence({
organizationId: 'org-123',
documentId: 'doc-456',
users: [{ userId: 'user-1', status: 'away' }],
});
Response
{ result: { status: 'success', message: 'Presence updated successfully.', data: {} } }
deletePresence
await sdk.api.presence.deletePresence({
organizationId: 'org-123',
documentId: 'doc-456',
userIds: ['user-1', 'user-2'],
});
Response
{ result: { status: 'success', message: 'Presence removed successfully.', data: {} } }
Livestate
Namespace: sdk.api.livestate
broadcastEvent
await sdk.api.livestate.broadcastEvent({
organizationId: 'org-123',
documentId: 'doc-1',
liveStateDataId: 'my-live-state',
data: { status: 'active', message: 'Hello World' },
merge: true,
});
Response
{ result: { status: 'success', message: 'Event broadcast successfully.', data: {} } }
Recordings
Namespace: sdk.api.recordings
getRecordings
await sdk.api.recordings.getRecordings({
organizationId: 'org-123',
documentId: 'doc-456',
recordingIds: ['rec-1'],
pageSize: 10,
pageToken: 'next-page-token',
});
Response
{
result: {
status: 'success',
message: 'Recorder annotations retrieved successfully.',
data: [
{
type: 'recorder',
recordingType: 'screen',
mode: 'floating',
metadata: { apiKey: 'YOUR_API_KEY', documentId: 'doc-456', organizationId: 'org-123' },
recordedTime: { duration: 4204.55, display: '00:00:04' },
displayName: 'Screen Recording 1773814490242.mp4',
annotationId: 'ypvmVTROaNU1qP4kq7Cc',
attachments: [{
attachmentId: 875113,
url: 'https://storage.googleapis.com/...',
mimeType: 'video/mp4',
name: 'recording_1773814490242.mp4',
type: 'mp4',
size: 103551
}],
latestVersion: 5
}
],
pageToken: 'nextPageToken'
}
}
Rewriter
Namespace: sdk.api.rewriter
Supports OpenAI, Anthropic, and Gemini models.
askAi
Note: askAi may take several seconds to respond. The SDK does not enforce a client-side timeout.
await sdk.api.rewriter.askAi({
model: 'gpt-4o',
prompt: 'Fix the grammar and spelling in the following text.',
text: 'Their going to the store to by some apples.',
});
Response
{
result: {
success: true,
text: 'The rewritten or processed text returned by the model.'
}
}
GDPR
Namespace: sdk.api.gdpr
deleteAllUserData
Note: deleteAllUserData is asynchronous and returns a job ID. Poll completion with getDeleteUserDataStatus.
await sdk.api.gdpr.deleteAllUserData({
userIds: ['user-1', 'user-2'],
organizationIds: ['org-123'],
});
Response
{
result: {
status: 'success',
message: 'User data deletion job queued.',
data: { jobId: 'delete-job-id' }
}
}
getAllUserData
await sdk.api.gdpr.getAllUserData({
organizationId: 'org-123',
userId: 'user-1',
pageToken: 'next-page-token',
});
Response
{
result: {
status: 'success',
message: 'Data fetched successfully.',
data: {
comments: [/* up to 100 items */],
reactions: [/* up to 100 items */],
recordings: [/* up to 100 items */],
notifications: [/* up to 100 items */]
},
nextPageToken: 'bhdwdqwjs298e39e479ddkeuw==329'
}
}
getDeleteUserDataStatus
await sdk.api.gdpr.getDeleteUserDataStatus({ jobId: 'job-id-from-delete-call' });
Response
{
result: {
status: 'success',
message: 'Data fetched successfully.',
data: {
isDeleteCompleted: true,
tasksLeft: 0,
lastTaskCompletedTime: 1748972106739
}
}
}
Workspace
Namespace: sdk.api.workspace
createWorkspace
await sdk.api.workspace.createWorkspace({
ownerEmail: 'owner@example.com',
workspaceName: 'My Workspace',
name: 'John Doe',
});
Response
{ result: { status: 'success', message: 'Workspace created successfully.', data: {} } }
getWorkspace
await sdk.api.workspace.getWorkspace({});
Response
{
result: {
status: 'success',
message: 'Workspace retrieved successfully.',
data: {
id: 'workspace_abc123',
name: 'My Workspace',
owner: { email: 'owner@example.com', id: 'owner_id_123', name: 'John Doe', avatar: '' },
authToken: 'eyJhbGciOiJSUzI1NiIs...',
apiKeyList: {
velt_api_key_1: { apiKeyName: 'John Doe Test API Key', id: 'velt_api_key_1', type: 'testing' }
}
}
}
}
createApiKey
await sdk.api.workspace.createApiKey({
ownerEmail: 'owner@example.com',
type: 'production',
createAuthToken: true,
apiKeyName: 'Production Key',
allowedDomains: ['example.com', '*.example.com'],
});
Response
{
result: {
status: 'success',
message: 'API key created successfully.',
data: { apiKey: 'velt_api_key_2', authToken: 'eyJhbGciOi...' }
}
}
updateApiKey
await sdk.api.workspace.updateApiKey({ apiKey: 'velt_api_key_1', apiKeyName: 'Renamed Key' });
Response
{ result: { status: 'success', message: 'API key updated successfully.', data: {} } }
getApiKeys
await sdk.api.workspace.getApiKeys({ pageSize: 50, pageToken: 'next-page-token' });
Response
{
result: {
status: 'success',
message: 'API keys retrieved successfully.',
data: [
{ id: 'velt_api_key_1', apiKeyName: 'Production Key', type: 'production' },
{ id: 'velt_api_key_2', apiKeyName: 'Testing Key', type: 'testing' }
],
nextPageToken: 'eyJsYXN0SWQiOiJ2ZWx0X2FwaV9rZXlfMiJ9'
}
}
await sdk.api.workspace.getApiKeyMetadata({});
Response
{
result: {
status: 'success',
message: 'API key metadata retrieved successfully.',
data: {
defaultDocumentAccessType: 'public',
planInfo: { type: 'sdk test' },
ownerEmail: 'owner@example.com'
}
}
}
resetAuthToken
await sdk.api.workspace.resetAuthToken({ apiKey: 'velt_api_key_1' });
Response
{
result: {
status: 'success',
message: 'Auth token reset successfully.',
data: { authToken: 'eyJhbGciOi...' }
}
}
getAuthTokens
await sdk.api.workspace.getAuthTokens({ apiKey: 'velt_api_key_1' });
Response
{
result: {
status: 'success',
message: 'Auth tokens retrieved successfully.',
data: {
apiKey: 'velt_api_key_1',
authTokens: [
{ token: 'eyJhbGciOiJSUzI1NiIs...', name: 'Default Auth Token', domains: [] }
]
}
}
}
addDomains
await sdk.api.workspace.addDomains({ domains: ['example.com', '*.firebase.com'] });
Response
{ result: { status: 'success', message: 'Domains added successfully.', data: {} } }
deleteDomains
await sdk.api.workspace.deleteDomains({ domains: ['example.com'] });
Response
{ result: { status: 'success', message: 'Domains deleted successfully.', data: {} } }
getDomains
await sdk.api.workspace.getDomains({});
Response
{
result: {
status: 'success',
message: 'Allowed domains retrieved successfully.',
data: { allowedDomains: ['localhost', '127.0.0.1', 'example.com'] }
}
}
getEmailStatus
await sdk.api.workspace.getEmailStatus({ ownerEmail: 'owner@example.com' });
Response
{
result: {
status: 'success',
message: 'Email verified and workspace reactivated',
data: { verified: true }
}
}
sendLoginLink
await sdk.api.workspace.sendLoginLink({
email: 'user@example.com',
continueUrl: 'https://app.example.com/dashboard',
});
Response
{ result: { status: 'success', message: 'Login link sent.', data: {} } }
getEmailConfig
await sdk.api.workspace.getEmailConfig({});
Response
{
result: {
status: 'success',
message: 'Email configuration retrieved successfully.',
data: {
useEmailService: false,
emailServiceConfig: { type: 'default', apiKey: '', fromEmail: '', fromCompany: '', commentTemplateId: '', tagTemplateId: '' }
}
}
}
updateEmailConfig
await sdk.api.workspace.updateEmailConfig({
useEmailService: true,
emailServiceConfig: { type: 'sendgrid', apiKey: 'sg-key', fromEmail: 'noreply@example.com' },
});
Response
{ result: { status: 'success', message: 'Email config updated successfully.', data: {} } }
getWebhookConfig
await sdk.api.workspace.getWebhookConfig({});
Response
{
result: {
status: 'success',
message: 'Webhook configuration retrieved successfully.',
data: {
useWebhookService: false,
webhookServiceConfig: { authToken: '', rawNotificationUrl: '', processedNotificationUrl: '' }
}
}
}
updateWebhookConfig
await sdk.api.workspace.updateWebhookConfig({
useWebhookService: true,
webhookServiceConfig: {
authToken: 'webhook-secret',
rawNotificationUrl: 'https://example.com/webhook/raw',
processedNotificationUrl: 'https://example.com/webhook/processed',
},
});
Response
{ result: { status: 'success', message: 'Webhook config updated successfully.', data: {} } }
Token
Namespace: sdk.api.token
getToken
- Generates a Velt auth token for a user via REST.
- Params: positional —
organizationId (string), userId (string), email (string, optional), isAdmin (boolean, optional)
- Returns: VeltApiResponse
Note: getToken takes positional arguments — not a request object.
await sdk.api.token.getToken('org-123', 'user-1', 'john@example.com', false);
Response
{
result: {
status: 'success',
message: 'Token generated successfully.',
data: { token: 'eyJhbGciOiJIUzI1NiIs...' }
}
}
Error Handling
The SDK exports five typed error classes:
| Class | Extends | When thrown |
|---|
VeltSDKError | Error | Base class for all SDK errors |
VeltDatabaseError | VeltSDKError | MongoDB connection or query failures |
VeltValidationError | VeltSDKError | Missing or invalid request parameters |
VeltTokenError | VeltSDKError | Token generation failures |
VeltApiError | VeltSDKError | REST API call failures |
import { VeltSDK, VeltDatabaseError, VeltApiError } from '@veltdev/node';
try {
const result = await sdk.api.organizations.getOrganizations({ organizationIds: ['org-123'] });
} catch (err) {
if (err instanceof VeltApiError) {
console.error('API call failed:', err.message);
} else if (err instanceof VeltDatabaseError) {
console.error('Database error:', err.message);
} else {
throw err;
}
}
Common self-hosting error codes returned in the response errorCode field:
INVALID_INPUT — Request data is malformed or missing required fields
INTERNAL_ERROR — Server-side error during processing
NOT_FOUND — Requested resource was not found
Distribution
The package ships both CommonJS (CJS) and ES Module (ESM) bundles with rolled-up .d.ts type definitions, making it compatible with all modern Node.js project setups.
// ESM
import { VeltSDK } from '@veltdev/node';
// CommonJS
const { VeltSDK } = require('@veltdev/node');