codiris-brainboard-sdk
v1.2.2
Published
Embed Codiris Brainboard whiteboard functionality into your applications
Maintainers
Readme
Codiris Brainboard SDK
Embed Codiris Brainboard whiteboard functionality into your applications. Build collaborative visual experiences with AI-powered features.
Installation
npm install codiris-brainboard-sdk
# or
yarn add codiris-brainboard-sdk
# or
pnpm add codiris-brainboard-sdkGetting Your API Key
Before using the SDK, you need to generate an API key:
- Go to Codiris Settings
- Navigate to Settings & Members → API Keys
- Click Create Key in the "Brainboard SDK Keys" section
- Give your key a name (e.g., "Production", "Development")
- Optionally, configure allowed domains for security
- Copy the generated key - it will only be shown once!
Key Format
SDK keys have the format: brb_live_xxxxxxxxxxxxxxxxxxxx (or brb_test_ for test keys)
Domain Restrictions
For production, you can restrict which domains can use your API key:
- Leave empty for development (allows all domains)
- Add specific domains like
app.example.com,localhost:3000 - Supports wildcard subdomains:
*.example.com
Quick Start
Basic Usage (Vanilla JS/TS)
import { BrainboardClient } from 'codiris-brainboard-sdk';
// Initialize the client
const client = new BrainboardClient({
apiKey: 'brb_live_your-api-key-here',
baseUrl: 'https://app.codiris.ai', // optional, defaults to production
});
// List boards
const { data: boards } = await client.listBoards();
// Create a board
const { data: board } = await client.createBoard({
name: 'My Board',
description: 'A collaborative whiteboard',
});
// Add objects to the board
await client.createObject(board.id, {
type: 'sticky',
x: 100,
y: 100,
width: 200,
height: 200,
text: 'Hello World!',
fill: '#ffeb3b',
});React Usage
import { BrainboardProvider, BrainboardEmbed, useBoards } from 'codiris-brainboard-sdk/react';
// Wrap your app with the provider
function App() {
return (
<BrainboardProvider
apiKey={process.env.NEXT_PUBLIC_BRAINBOARD_API_KEY}
baseUrl={process.env.NEXT_PUBLIC_BRAINBOARD_BASE_URL || "https://talk.codiris.build/api"}
>
<MyComponent />
</BrainboardProvider>
);
}
// Use the embed component
function MyComponent() {
const { boards, createBoard } = useBoards();
return (
<div>
<button onClick={() => createBoard({ name: 'New Board' })}>
Create Board
</button>
{boards[0] && (
<BrainboardEmbed
boardId={boards[0].id}
width="100%"
height="600px"
showToolbar
onBoardChange={(board) => console.log('Board updated:', board)}
/>
)}
</div>
);
}Important: The BrainboardEmbed component automatically includes your API key in the iframe URL for authentication. This is necessary because iframes cannot send custom HTTP headers. To protect your API key:
- Use environment variables - Never hardcode your API key
- Set domain restrictions - Configure allowed domains in your API key settings
- Use HTTPS only - Always serve your app over HTTPS in production
Features
Board Management
// List boards with filtering
const { data } = await client.listBoards({
status: 'active',
search: 'project',
page: 1,
pageSize: 20,
});
// Get a specific board
const { data: board } = await client.getBoard('board-id');
// Update a board
await client.updateBoard('board-id', {
name: 'Updated Name',
isPublic: true,
});
// Delete a board
await client.deleteBoard('board-id');
// Duplicate a board
const { data: newBoard } = await client.duplicateBoard('board-id', 'Copy of Board');Objects (Canvas Elements)
// Create various object types
await client.createObject(boardId, {
type: 'text',
x: 100, y: 100,
text: 'Hello World',
fontSize: 24,
});
await client.createObject(boardId, {
type: 'shape',
x: 200, y: 200,
width: 150, height: 100,
shapeType: 'rectangle',
fill: '#3b82f6',
});
await client.createObject(boardId, {
type: 'sticky',
x: 400, y: 100,
width: 200, height: 200,
text: 'Idea #1',
fill: '#fef08a',
});
// Batch create
await client.createObjects(boardId, [
{ type: 'sticky', x: 100, y: 100, text: 'Task 1' },
{ type: 'sticky', x: 320, y: 100, text: 'Task 2' },
{ type: 'sticky', x: 540, y: 100, text: 'Task 3' },
]);
// Update objects
await client.updateObject(boardId, objectId, {
text: 'Updated text',
fill: '#22c55e',
});
// Delete objects
await client.deleteObject(boardId, objectId);
await client.deleteObjects(boardId, [id1, id2, id3]);Supported Object Types
| Type | Description |
|------|-------------|
| sticky | Sticky note with text |
| text | Text block |
| shape | Shapes (rectangle, circle, triangle, diamond, star, etc.) |
| line | Connecting line |
| arrow | Arrow connector |
| image | Image element |
| card | Card with title, description, tags |
| table | Data table |
| kanban | Kanban board |
| code | Code block with syntax highlighting |
| chart | Chart (line, bar, pie, etc.) |
| embed | External embed (YouTube, Figma, etc.) |
| frame | Presentation frame |
| draw | Freehand drawing |
Collaboration
// Get board members
const { data: members } = await client.getMembers(boardId);
// Invite a member
await client.inviteMember(boardId, '[email protected]', 'editor');
// Update member role
await client.updateMemberRole(boardId, memberId, 'viewer');
// Remove a member
await client.removeMember(boardId, memberId);
// Generate share link
const { data } = await client.generateShareLink(boardId, {
canEdit: false,
expiresAt: '2024-12-31T23:59:59Z',
});
console.log(data.shareUrl);Comments
// Get comments
const { data: comments } = await client.getComments(boardId);
// Add a comment
await client.addComment(boardId, 'Great idea!', objectId);
// Reply to a comment
await client.addComment(boardId, 'I agree!', objectId, parentCommentId);
// Resolve a comment
await client.resolveComment(boardId, commentId);AI Features
// Generate content
const { data } = await client.generateContent({
prompt: 'Create a user journey map for an e-commerce checkout flow',
type: 'diagram',
});
// Chat with AI about board content
const { data: response } = await client.chat(boardId, [
{ role: 'user', content: 'What are the main themes on this board?' }
]);
console.log(response.content);
console.log(response.sources); // Cited sources from the board
// Execute natural language commands
await client.executeCommand(boardId, 'make all sticky notes blue');
await client.executeCommand(boardId, 'align selected items to the left', selectedIds);
// Generate audio overview
const { data: audio } = await client.generateAudioOverview(boardId, 'podcast');
console.log(audio.audioUrl, audio.script);Templates
// List templates
const { data: templates } = await client.listTemplates('brainstorming');
// Create from template
const { data: board } = await client.createFromTemplate(
'template-id',
'My Brainstorm Session'
);
// Save board as template
await client.saveAsTemplate(boardId, 'My Template', 'Reusable board layout');Import & Export
// Import from URL
await client.importFromUrl(boardId, 'https://example.com/article', { x: 100, y: 100 });
// Extract from PDF
await client.extractPdf(boardId, 'https://example.com/document.pdf');
// Create from interview data
await client.createFromInterview(interviewId, 'Interview Summary Board');
// Export
const { data: json } = await client.exportAsJson(boardId);
const { data: image } = await client.exportAsImage(boardId, 'png', { scale: 2 });
const { data: pdf } = await client.exportAsPdf(boardId, { includeFrames: true });React Hooks
useBoard(boardId)
const { board, loading, error, updateBoard } = useBoard('board-id');useBoards(options?)
const { boards, total, loading, createBoard, deleteBoard } = useBoards({
status: 'active',
page: 1,
});useBoardObjects(boardId)
const {
objects,
selectedObjects,
createObject,
updateObject,
deleteObject,
selectObject,
clearSelection,
} = useBoardObjects('board-id');useBoardMembers(boardId)
const { members, inviteMember, removeMember } = useBoardMembers('board-id');useBoardComments(boardId, objectId?)
const { comments, addComment, deleteComment } = useBoardComments('board-id');useBrainboardChat(boardId)
const { messages, loading, sendMessage, clearMessages } = useBrainboardChat('board-id');
// Send message with source grounding
await sendMessage('What patterns do you see?', true);useBrainboardGenerate()
const { loading, generate } = useBrainboardGenerate();
const result = await generate({
prompt: 'Create a SWOT analysis template',
type: 'diagram',
});useBrainboardEvent(type, callback)
useBrainboardEvent('object:created', (event) => {
console.log('New object:', event.data);
});useTemplates(category?)
const { templates, createFromTemplate } = useTemplates('planning');React Components
<BrainboardEmbed />
Full-featured embedded board editor.
<BrainboardEmbed
boardId="board-id"
width="100%"
height="600px"
readOnly={false}
showToolbar={true}
showSidebar={false}
showComments={true}
showMinimap={true}
theme="light"
onReady={() => console.log('Ready!')}
onBoardChange={(board) => console.log(board)}
onObjectSelect={(objects) => console.log(objects)}
/><BrainboardViewer />
Read-only board viewer.
<BrainboardViewer
boardId="board-id"
width="100%"
height="400px"
showNavigation={true}
autoFit={true}
/><BrainboardThumbnail />
Board thumbnail preview.
<BrainboardThumbnail
board={board}
width={200}
height={150}
onClick={() => navigate(`/boards/${board.id}`)}
/><BrainboardList />
Grid view of boards.
<BrainboardList
boards={boards}
gridColumns={3}
onSelect={(board) => setSelectedBoard(board)}
emptyMessage="No boards yet"
/>Events
Listen to real-time events:
import { globalEvents } from 'codiris-brainboard-sdk';
globalEvents.on('board:updated', (event) => {
console.log('Board updated:', event.data);
});
globalEvents.on('object:created', (event) => {
console.log('Object created:', event.data);
});
globalEvents.on('user:joined', (event) => {
console.log('User joined:', event.data);
});
// Listen to all events
globalEvents.onAll((event) => {
console.log(`${event.type}:`, event.data);
});Event Types
| Event | Description |
|-------|-------------|
| board:loaded | Board finished loading |
| board:updated | Board properties changed |
| object:created | New object added |
| object:updated | Object modified |
| object:deleted | Object removed |
| object:selected | Objects selected |
| object:deselected | Selection cleared |
| camera:moved | Viewport changed |
| user:joined | User joined the board |
| user:left | User left the board |
| cursor:moved | User cursor moved |
| comment:added | New comment added |
| error | Error occurred |
Configuration
const client = new BrainboardClient({
// Required
apiKey: 'your-api-key',
// Optional
baseUrl: 'https://app.codiris.ai/api', // Custom API endpoint
workspaceId: 'workspace-id', // Default workspace
userId: 'user-id', // Current user ID
userEmail: '[email protected]', // Current user email
userName: 'User Name', // Current user name
externalUserId: 'your-user-123', // External user ID for board isolation
debug: false, // Enable debug logging
});User Isolation (Multi-tenancy)
When embedding Brainboard in your application, you can isolate boards per user using the externalUserId feature. This allows each user in your system to have their own private set of boards without seeing boards from other users.
How It Works
- Pass your user's unique ID as
externalUserIdwhen initializing the client - When creating boards, they are automatically tagged with this external user ID
- When listing boards, only boards belonging to that user are returned
Example: Per-User Board Isolation
// Initialize client with your user's ID
const client = new BrainboardClient({
apiKey: 'brb_live_your-api-key',
externalUserId: currentUser.id, // Your application's user ID
});
// This user only sees their own boards
const { data: boards } = await client.listBoards();
// Boards created are tagged with this user's ID
const { data: board } = await client.createBoard({
name: "Alice's Board",
});
// board.externalUserId === currentUser.idUsing Headers Directly
You can also pass the external user ID via HTTP headers:
// When making API requests directly
fetch('/api/brainboard/boards', {
headers: {
'Authorization': `Bearer ${apiKey}`,
'X-External-User-Id': 'your-user-123',
},
});Switching Users
To demonstrate different user views (useful for admin/support scenarios):
function UserBoardView({ userId }: { userId: string }) {
return (
<BrainboardProvider
apiKey={apiKey}
externalUserId={userId} // Each user sees only their boards
>
<BoardList />
</BrainboardProvider>
);
}Query Parameters
You can also filter boards by external user ID using query parameters:
GET /api/brainboard/boards?externalUserId=user_alice_123Testing User Isolation
Visit /test/sdk in your Codiris dashboard to test user isolation. The test bench allows you to:
- Connect with your API key
- Switch between simulated users (Alice, Bob, Charlie)
- Create boards for each user
- See how boards are isolated per user
TypeScript Support
The SDK is fully typed. Import types as needed:
import type {
Board,
BoardObject,
BoardMember,
CreateBoardInput,
CreateObjectInput,
BrainboardConfig,
} from 'codiris-brainboard-sdk';Error Handling
All API methods return a consistent response format:
const response = await client.getBoard('board-id');
if (response.success) {
console.log(response.data);
} else {
console.error(response.error);
}With React hooks, errors are exposed via the error property:
const { board, loading, error } = useBoard('board-id');
if (error) {
return <div>Error: {error.message}</div>;
}Security Best Practices
Protect Your API Keys
- Never commit API keys to version control - Use environment variables instead
- Use domain restrictions in production - Limit which domains can use your key
- Create separate keys for different environments - Use
brb_test_keys for development - Rotate keys periodically - Revoke and regenerate keys if compromised
- Monitor usage - Check the API Keys dashboard for unusual activity
Environment Variables
# .env.local (DO NOT commit this file)
NEXT_PUBLIC_BRAINBOARD_API_KEY=brb_live_xxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_BRAINBOARD_BASE_URL=https://app.codiris.ai// Use environment variables
<BrainboardProvider
apiKey={process.env.NEXT_PUBLIC_BRAINBOARD_API_KEY}
baseUrl={process.env.NEXT_PUBLIC_BRAINBOARD_BASE_URL}
>
<App />
</BrainboardProvider>Managing Keys
You can manage your SDK keys at any time:
- Create new keys: Settings → API Keys → Create Key
- View usage: See request counts and last used date
- Update domains: Modify allowed domains for existing keys
- Revoke keys: Deactivate keys that are no longer needed
Troubleshooting
Having issues? Check our Troubleshooting Guide for common problems and solutions:
- 401 Authentication Required - API key configuration issues
- Environment Variables Not Loading - .env file setup
- Board Not Loading - Access and permissions issues
- CORS Errors - Domain and security configuration
Support
- Documentation: https://docs.codiris.ai
- Troubleshooting: TROUBLESHOOTING.md
- GitHub Issues: https://github.com/codiris/brainboard-sdk/issues
- Email: [email protected]
License
MIT
