
Company News
Free Business Plan Upgrades for Open Source Maintainers
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.
@contio/partner-sdk
Advanced tools
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.
FAQs
Official SDK for Contio MeetingOS Partner API
We found that @contio/partner-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.