Official TypeScript/JavaScript SDK for integrating with the Contio Partner API.
📚 Full Documentation: docs.contio.ai/partner-api
npm install @contio/partner-sdk
import { ContioPartnerSDK } from '@contio/partner-sdk';
const { oauth, user } = ContioPartnerSDK.forUser({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
redirectUri: 'https://your-app.com/callback'
});
// Generate authorization URL
const authUrl = oauth.getAuthorizationUrl('csrf-state');
// After user authorizes, exchange code for tokens
const tokens = await oauth.exchangeCodeForToken(authorizationCode);
// Access user data
const meetings = await user.getMeetings();
const actionItems = await user.getActionItems();
Provision new users into existing shared workspaces instead of creating individual workspaces:
import { ContioPartnerSDK } from '@contio/partner-sdk';
const { oauth } = ContioPartnerSDK.forUser({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
redirectUri: 'https://your-app.com/callback'
});
// Provision a new user into a shared workspace
const result = await oauth.initiatePartnerAuth(
'newuser@example.com',
'New User',
{ workspace_id: 'existing-workspace-uuid' }
);
// Provision as a workspace admin
const adminResult = await oauth.initiatePartnerAuth(
'admin@example.com',
'Admin User',
{ workspace_id: 'existing-workspace-uuid', is_admin: true }
);
// Check a user's workspace after provisioning
const profile = await user.getUserProfile();
console.log(`Workspace: ${profile.workspace_name} (${profile.workspace_role})`);
import { ContioPartnerSDK } from '@contio/partner-sdk';
const { admin } = ContioPartnerSDK.forAdmin({
apiKey: 'your-api-key'
});
const automations = await admin.getAutomations();
const stats = await admin.getStats();
const disabledApp = await admin.updateWebhookStatus({
enabled: false
});
const filteredApp = await admin.setWebhookFilter({
type: 'include',
events: ['meeting.created', 'meeting.completed']
});
const unfilteredApp = await admin.removeWebhookFilter();
console.log(disabledApp.webhook_enabled);
console.log(filteredApp.webhook_filter);
console.log(unfilteredApp.webhook_filter); // null
Access user calendar events and retrieve detailed event information:
// List calendar events in a date range
const events = await user.getCalendarEvents({
start: '2026-01-01T00:00:00Z',
end: '2026-01-31T23:59:59Z'
});
// Get detailed information about a specific calendar event
const event = await user.getCalendarEvent('cal-event-123');
console.log(`Event: ${event.title}`);
console.log(`Organizer: ${event.organizer?.email}`);
// Create a meeting from a calendar event
const result = await user.createMeetingFromCalendarEvent('cal-event-123');
console.log(`Created: ${result.created}, Meeting ID: ${result.meeting?.id}`);
The SDK supports all Partner API webhook events with full TypeScript typing:
Meeting Events:
meeting.created - New meeting createdmeeting.updated - Meeting properties changed (title, scheduled time, etc.)meeting.completed - Meeting ended with notes/summary availableCalendar Events:
calendar_event.created - Calendar event synced from external calendarcalendar_event.updated - Calendar event updated in external calendarcalendar_event.deleted - Calendar event cancelled/deletedAgenda Items:
agenda_item.created - Agenda item created in meeting or backlogagenda_item.updated - Agenda item title, status, or properties changedagenda_item.deleted - Agenda item removedAction Items:
action_item.created - New action item createdaction_item.updated - Action item status or details changedaction_item.completed - Action item marked as completedOther Events:
automation.assignment.created - Action item assigned to your automationparticipant.added - Participant(s) added to meetingparticipant.removed - Participant removed from meetinguser.connection.revoked - User revoked connection to your appimport { verifyWebhookSignature, parseWebhook } from '@contio/partner-sdk';
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-contio-signature'] as string;
try {
const event = parseWebhook(req.body, signature, process.env.WEBHOOK_SECRET!);
// Handle event...
res.status(200).json({ received: true });
} catch (error) {
res.status(401).json({ error: 'Invalid signature' });
}
});
All API errors are thrown as ContioAPIError instances with structured information:
import { ContioAPIError } from '@contio/partner-sdk';
try {
const meeting = await user.getMeeting('invalid-id');
} catch (error) {
if (error instanceof ContioAPIError) {
console.error('Code:', error.code); // e.g., 'not_found', 'unauthorized'
console.error('Message:', error.message); // Human-readable description
console.error('Status:', error.statusCode); // HTTP status code (404, 401, etc.)
console.error('Response:', error.response); // Full error response body
}
}
| Code | Status | Description |
|---|---|---|
unauthorized |
401 | Invalid or expired access token |
forbidden |
403 | Insufficient permissions for this resource |
not_found |
404 | Resource does not exist |
validation_error |
400 | Invalid request parameters |
rate_limited |
429 | Too many requests; retry after backoff |
workspace_not_found |
400 | Specified workspace_id does not exist |
workspace_not_authorized |
403 | Workspace not owned by a user from the same partner |
workspace_conflict |
409 | User already belongs to a different workspace |
internal_error |
500 | Server error; retry with exponential backoff |
The SDK automatically retries transient errors (5xx) with exponential backoff.
For complete documentation, visit:
Contio uses opaque tokens for improved security. Access tokens (cto_at_v1_...) and refresh tokens (cto_rt_v1_...) contain no readable claims.
| Token | Format | Validity |
|---|---|---|
| Authorization code | Opaque | 5 minutes |
| Access token | cto_at_v1_... |
24 hours |
| Refresh token | cto_rt_v1_... |
30 days |
| ID token | JWT | 24 hours |
Important: Do not attempt to decode or parse access/refresh tokens. Use introspection to get token metadata:
const tokenInfo = await oauth.introspectToken(accessToken);
console.log('Scopes:', tokenInfo.scope);
console.log('Expires:', new Date(tokenInfo.exp * 1000));
// Example: Storing tokens securely (server-side)
async function storeTokens(userId: string, tokens: AuthTokens) {
await db.userTokens.upsert({
where: { userId },
data: {
accessToken: encrypt(tokens.accessToken),
refreshToken: encrypt(tokens.refreshToken),
expiresAt: tokens.expiresAt,
},
});
}
parseWebhook() or verifyWebhookSignature()express.raw() to preserve the raw request body for signature verification// Track processed webhook IDs to handle retries
const processedEvents = new Set<string>();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const event = parseWebhook(req.body, signature, secret);
if (processedEvents.has(event.event_id)) {
return res.status(200).json({ received: true, duplicate: true });
}
processedEvents.add(event.event_id);
// Process event...
});
git clone https://github.com/Contio-AI/partner-sdk.git
cd partner-sdk
npm install
npm run build
npm test # Run all tests
npm test -- --coverage # Run with coverage report
npm test -- oauth.test.ts # Run specific test file
| Script | Description |
|---|---|
npm run build |
Compile TypeScript to JavaScript |
npm test |
Run the test suite |
npm run lint |
Run ESLint on source files |
npm run docs |
Generate TypeDoc documentation |
npm run gen-types |
Regenerate types from OpenAPI spec |
For support, contact partner-support@contio.ai
This SDK is licensed under the MIT License. See the LICENSE file for details.
Note: This license applies to the SDK source code only. Use of the Contio Partner API is governed by your Partner Agreement with Contio, Inc.