Official TypeScript/JavaScript SDK for integrating with the Contio Partner API.
📚 Full Documentation: docs.contio.ai/partner-api
npm install @contio/partner-sdk- Node.js 22.0.0 or higher (LTS)
- TypeScript 4.5.0 or higher (for TypeScript users)
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); // nullAccess 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 available
Calendar Events:
calendar_event.created- Calendar event synced from external calendarcalendar_event.updated- Calendar event updated in external calendarcalendar_event.deleted- Calendar event cancelled/deleted
Agenda Items:
agenda_item.created- Agenda item created in meeting or backlogagenda_item.updated- Agenda item title, status, or properties changedagenda_item.deleted- Agenda item removed
Action Items:
action_item.created- New action item createdaction_item.updated- Action item status or details changedaction_item.completed- Action item marked as completed
Other 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 app
import { 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:
- Quick Start - Get up and running
- Authentication - OAuth 2.0 and API keys
- API Reference - Complete method reference
- OAuth Flow - Detailed OAuth implementation
- Webhook Events - Real-time notifications
- Credential Management - Secure credential rotation
- Troubleshooting - Common issues and solutions
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));- Never store tokens in client-side code (localStorage, cookies accessible to JS)
- Use secure, server-side storage (encrypted database, secure session store)
- Refresh tokens are sensitive — treat them like passwords
- Set appropriate token lifetimes — access tokens expire in 24 hours by default
// 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,
},
});
}- Always verify signatures using
parseWebhook()orverifyWebhookSignature() - Use
express.raw()to preserve the raw request body for signature verification - Implement idempotency — webhooks may be delivered more than once
- Respond quickly (< 5 seconds) to avoid timeout retries
// 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 buildnpm 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.