Contio Partner SDK
Official TypeScript/JavaScript SDK for integrating with the Contio Partner API.
📚 Full Documentation: docs.contio.ai/partner-api
Installation
npm install @contio/partner-sdk
Requirements
- Node.js 22.0.0 or higher (LTS)
- TypeScript 4.5.0 or higher (for TypeScript users)
Quick Start
OAuth User Operations
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'
});
const authUrl = oauth.getAuthorizationUrl('csrf-state');
const tokens = await oauth.exchangeCodeForToken(authorizationCode);
const meetings = await user.getMeetings();
const actionItems = await user.getActionItems();
Shared Workspace Provisioning
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'
});
const result = await oauth.initiatePartnerAuth(
'newuser@example.com',
'New User',
{ workspace_id: 'existing-workspace-uuid' }
);
const adminResult = await oauth.initiatePartnerAuth(
'admin@example.com',
'Admin User',
{ workspace_id: 'existing-workspace-uuid', is_admin: true }
);
const profile = await user.getUserProfile();
console.log(`Workspace: ${profile.workspace_name} (${profile.workspace_role})`);
API Key Admin Operations
import { ContioPartnerSDK } from '@contio/partner-sdk';
const { admin } = ContioPartnerSDK.forAdmin({
apiKey: 'your-api-key'
});
const automations = await admin.getAutomations();
const stats = await admin.getStats();
Webhook Management
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);
Key Features
Calendar Events
Access user calendar events and retrieve detailed event information:
const events = await user.getCalendarEvents({
start: '2026-01-01T00:00:00Z',
end: '2026-01-31T23:59:59Z'
});
const event = await user.getCalendarEvent('cal-event-123');
console.log(`Event: ${event.title}`);
console.log(`Organizer: ${event.organizer?.email}`);
const result = await user.createMeetingFromCalendarEvent('cal-event-123');
console.log(`Created: ${result.created}, Meeting ID: ${result.meeting?.id}`);
Webhook Events
The SDK supports all Partner API webhook events with full TypeScript typing:
Meeting Events:
meeting.created - New meeting created
meeting.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 calendar
calendar_event.updated - Calendar event updated in external calendar
calendar_event.deleted - Calendar event cancelled/deleted
Agenda Items:
agenda_item.created - Agenda item created in meeting or backlog
agenda_item.updated - Agenda item title, status, or properties changed
agenda_item.deleted - Agenda item removed
Action Items:
action_item.created - New action item created
action_item.updated - Action item status or details changed
action_item.completed - Action item marked as completed
Other Events:
automation.assignment.created - Action item assigned to your automation
participant.added - Participant(s) added to meeting
participant.removed - Participant removed from meeting
user.connection.revoked - User revoked connection to your app
Webhook Verification
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!);
res.status(200).json({ received: true });
} catch (error) {
res.status(401).json({ error: 'Invalid signature' });
}
});
Error Handling
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);
console.error('Message:', error.message);
console.error('Status:', error.statusCode);
console.error('Response:', error.response);
}
}
Common Error Codes
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.
Documentation
For complete documentation, visit:
Token Format
Contio uses opaque tokens for improved security. Access tokens (cto_at_v1_...) and refresh tokens (cto_rt_v1_...) contain no readable claims.
| 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));
Security Best Practices
Token Storage
- 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
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,
},
});
}
Webhook Security
- Always verify signatures using
parseWebhook() or verifyWebhookSignature()
- 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
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);
});
Development
Building from Source
git clone https://github.com/Contio-AI/partner-sdk.git
cd partner-sdk
npm install
npm run build
Running Tests
npm test
npm test -- --coverage
npm test -- oauth.test.ts
Scripts
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 |
Support
For support, contact partner-support@contio.ai
License
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.