Overview
Velt supports self-hosting your users’ personally identifiable information (PII):- Only the userId is stored on Velt servers, keeping sensitive user metadata on your infrastructure
- Velt Components automatically hydrate user details in the frontend by fetching from your configured data provider
- This gives you full control over user data while maintaining all Velt functionality
How does it work?
- When the SDK is initialized, it will call the
UserDataProvideryou configure with the list of userIds that it needs to fetch for the currently set user, organization, document, etc. - The
UserDataProvidertakes in a list of userIds and returns a Record object with the userIds as keys and the user data as values.
Implementation Approaches
You can implement user self-hosting using either of these approaches:- Endpoint based: Provide an endpoint URL and let the SDK handle HTTP requests
- Function based: Implement the
getmethod yourself
| Feature | Function based | Endpoint based |
|---|---|---|
| Best For | Complex setups requiring middleware logic, dynamic headers, or transformation before sending | Standard REST APIs where you just need to pass the request “as-is” to the backend |
| Implementation | You write the fetch() or axios code | You provide the url string and headers object |
| Flexibility | High | Medium |
| Speed | Medium | High |
Endpoint based DataProvider
Instead of implementing custom methods, you can configure an endpoint directly and let the SDK handle HTTP requests.getConfig
Config-based endpoint for fetching users. The SDK automatically makes HTTP POST requests with the request body.- Type:
ResolverEndpointConfig - Request body format:
GetUserResolverRequest-{ organizationId: string, userIds: string[] } - Response format:
ResolverResponse<Record<string, User>>
The config-based approach uses a different request format than the custom methods approach. It passes
{ organizationId, userIds } instead of just userIds.- React / Next.js
- Other Frameworks
Endpoint based Complete Example
- React / Next.js
- Other Frameworks
Function based DataProvider
Here are the methods that you need to implement on the data provider:get
Method to fetch users from your database.- Param:
string[]: Array of userIds to fetch - Return:
Promise<Record<string, User>>orPromise<ResolverResponse<Record<string, User>>>
Both response formats are supported for backward compatibility:
- Old format:
Record<string, User>- Returns user data directly - New format:
ResolverResponse<Record<string, User>>- Returns{ data, success, statusCode, message?, timestamp? }
- Frontend Example
- Backend Endpoint Example (MongoDB)
- Backend Endpoint Example (PostgreSQL)
config
Configuration for the user data provider.- Type:
ResolverConfig. Relevant properties:resolveUsersConfig:ResolveUsersConfig. Controls whether Velt issues user-resolver requests during initialization to fetch contact lists at the organization, folder, and document levels. Use this to optimize performance in environments with a large number of users by preventing unnecessary user-data fetches. You can selectively disable user-resolver requests for specific scopes and instead provide your own user data via the custom autocomplete feature instead.organization: boolean - Enable/disable user requests for organization users (default: true)document: boolean - Enable/disable user requests for document users (default: true)folder: boolean - Enable/disable user requests for folder users (default: true)
Function based Complete Example
- React / Next.js
- Other Frameworks
Anonymous User Resolution
When a user who is not part of the contact list is tagged by email in a comment, they won’t have auserId. The AnonymousUserDataProvider resolves these email → userId mappings automatically. When a comment is saved and a tagged contact or to recipient has an email but no userId, the SDK calls the registered provider to look up the userId, backfills it into the comment data before persisting, and optionally writes a stub user record to the organization database.
- Type:
AnonymousUserDataProviderresolveUserIdsByEmail: Callback that maps email addresses to user IDs. Called automatically at comment save time.- Param:
ResolveUserIdsByEmailRequest-{ organizationId: string, documentId?: string, folderId?: string, emails: string[] } - Return:
Promise<ResolverResponse<Record<string, string>>>-{ statusCode, success, data: { [email]: userId } }
- Param:
config: Optional configuration for timeout and retry behavior.- Type:
AnonymousUserDataProviderConfig resolveTimeout:number- Timeout in milliseconds for the resolve callgetRetryConfig:RetryConfig-{ retryCount, retryDelay }
- Type:
- Results are cached in memory for the session; emails already resolved are not re-fetched.
- On timeout or error, the provider returns whatever was cached and proceeds without the unresolved user IDs.
- If no
UserDataProvideris configured, resolved user IDs are automatically backfilled to the organization database as stub user records ({ userId, name: email, email }). - If a
UserDataProvideris already configured, the org DB backfill is skipped.
- React / Next.js
- Other Frameworks
Sample Data
- Stored on your database
- Stored on Velt servers
Debugging
You can subscribe todataProvider events to monitor and debug get operations. The event includes a moduleName field that identifies which module triggered the resolver call, helping you trace data provider requests.
You can also use the Velt Chrome DevTools extension to inspect and debug your Velt implementation.
Type: UserResolverModuleName
- React / Next.js
- Other Frameworks

