Skip to content

Deep Linking Guide

This guide explains how to use deep links to navigate users directly to specific locations in the Contio application, both for SSO-enabled integrations and for users with active sessions.

Overview

Contio supports three types of deep linking:

  1. SSO Deep Links (/p/{slug}) - For SSO-enabled integrations where authentication is required
  2. Session-Based Deep Links (/m/{mtg-id}, /meetings/{mtg-id}, contio://) - For users with active sessions
  3. App Page Deep Links (/open/{path}) - For linking directly to any app page (onboarding, marketing emails)

Choose the appropriate deep linking method based on your integration type and whether users are already authenticated in Contio.


If your users already have active Contio sessions (either in the browser or desktop app), you can use direct deep links without going through the SSO flow. These links work for both web and desktop experiences.

Meeting Landing Page: /m/{mtg-id}

The /m/{mtg-id} endpoint provides a stable landing page that intelligently routes users to the best experience:

https://app.contio.ai/m/{meeting-id}

Features: - Desktop App Detection: Detects if the Contio desktop app is installed - Download Prompt: Invites users to download the desktop app if not installed - Web Fallback: Provides a "Continue in browser" option for web-only access - Session Aware: Works for users with active Contio sessions

Use Cases: - Email notifications with meeting links - Calendar integrations - Partner app notifications - General-purpose meeting sharing

Example:

function generateMeetingLink(meetingId: string): string {
  return `https://app.contio.ai/m/${meetingId}`;
}

// Usage in email template
const meetingLink = generateMeetingLink('550e8400-e29b-41d4-a716-446655440000');
// https://app.contio.ai/m/550e8400-e29b-41d4-a716-446655440000

For users who prefer or require the web experience, use the direct meeting view URL:

https://app.contio.ai/meetings/{meeting-id}

Features: - Direct Access: Opens directly to the meeting view in the web app - No Download Prompt: Skips the landing page entirely - Full Feature Parity: Viewing, editing, and action item management (capture excluded)

Use Cases: - Web-only environments (Chromebooks, locked-down systems) - Users who explicitly prefer browser experience - Embedded iframes or web views

Example:

function generateWebMeetingLink(meetingId: string): string {
  return `https://app.contio.ai/meetings/${meetingId}`;
}

Web Experience Limitations

The web experience does not support meeting capture (audio recording and transcription). Users who need to capture meetings should use the desktop app via /m/{mtg-id} or the desktop deep link scheme.

For direct desktop app integration, use the custom URL scheme:

contio://app/meetings/{meeting-id}

Features: - Instant Launch: Opens the desktop app directly (if installed) - Full Feature Set: Includes meeting capture capabilities - Background Launch: Can be triggered from any application

Use Cases: - Desktop application integrations - System notifications - Command-line tools - Native mobile apps (iOS/Android)

Example:

function openMeetingInDesktop(meetingId: string): void {
  const desktopUrl = `contio://app/meetings/${meetingId}`;
  window.location.href = desktopUrl;

  // Fallback to landing page if desktop app not installed
  setTimeout(() => {
    window.location.href = `https://app.contio.ai/m/${meetingId}`;
  }, 1000);
}

URL Scheme Differences by Environment

  • Beta/Staging: contio-beta://app/meetings/{mtg-id}
  • Production: contio://app/meetings/{mtg-id}

Ensure you use the correct scheme for your deployment environment.

Getting Meeting IDs

Meeting IDs are available through both the Partner API and webhook events:

Via API:

const sdk = ContioPartnerSDK.forUser({ /* OAuth config */ });
const meetings = await sdk.meetings.list();

meetings.data.forEach(meeting => {
  const landingPageLink = `https://app.contio.ai/m/${meeting.id}`;
  const webLink = `https://app.contio.ai/meetings/${meeting.id}`;
  const desktopLink = `contio://app/meetings/${meeting.id}`;
});

Via Webhooks:

{
  "event": "meeting.completed",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "title": "Q1 Planning Session",
    "status": "completed"
  }
}

Complete Example: Multi-Platform Deep Linking

Here's a complete example that handles deep linking across different platforms:

interface DeepLinkTarget {
  meetingId: string;
  preferDesktop?: boolean;
  forceWeb?: boolean;
}

function generateDeepLink(target: DeepLinkTarget): string {
  const { meetingId, preferDesktop, forceWeb } = target;

  // Force web experience
  if (forceWeb) {
    return `https://app.contio.ai/meetings/${meetingId}`;
  }

  // Prefer desktop (with fallback)
  if (preferDesktop) {
    return `contio://app/meetings/${meetingId}`;
  }

  // Default: landing page with smart routing
  return `https://app.contio.ai/m/${meetingId}`;
}

// Usage examples
const defaultLink = generateDeepLink({
  meetingId: '550e8400-e29b-41d4-a716-446655440000'
});
// https://app.contio.ai/m/550e8400-e29b-41d4-a716-446655440000

const webOnlyLink = generateDeepLink({
  meetingId: '550e8400-e29b-41d4-a716-446655440000',
  forceWeb: true
});
// https://app.contio.ai/meetings/550e8400-e29b-41d4-a716-446655440000

const desktopLink = generateDeepLink({
  meetingId: '550e8400-e29b-41d4-a716-446655440000',
  preferDesktop: true
});
// contio://app/meetings/550e8400-e29b-41d4-a716-446655440000

The /open/{path} endpoint provides deep links to any page within the Contio application. The path after /open/ is forwarded verbatim to the desktop app via the custom URL scheme.

https://app.contio.ai/open/{any-valid-app-path}

Features: - Path Passthrough: Any valid app route can be used — no pre-defined slug list - Desktop App Detection: Attempts to open the Contio desktop app via the custom URL scheme - Branded Fallback: Shows an "Open in App" / "Continue in Browser" card if the desktop app isn't installed - Query Parameter Forwarding: Query params are forwarded to both the desktop deep link and browser fallback

Common Examples:

URL Desktop Deep Link Browser Fallback
/open/ contio://app/ /
/open/settings/calendars contio://app/settings/calendars /settings/calendars
/open/settings/users contio://app/settings/users /settings/users
/open/settings/billing contio://app/settings/billing /settings/billing
/open/?chat=new contio://app/?chat=new /?chat=new
/open/?chat=new&prefill=Hi contio://app/?chat=new&prefill=Hi /?chat=new&prefill=Hi
/open/meetings/abc-123 contio://app/meetings/abc-123 /meetings/abc-123

Chat Message Pre-fill:

The prefill query parameter can be combined with ?chat=new to pre-fill the AI chat input box with a message without submitting it. The user sees the text in the input field and can review or edit before sending.

https://app.contio.ai/open/?chat=new&prefill=Summarize%20my%20meetings%20this%20week

Use Cases: - Onboarding email sequences (e.g. "Connect your calendar" CTA) - Marketing emails highlighting specific features - In-app help articles linking to settings pages - Growth campaigns driving users to invite teammates - Prompted AI interactions (e.g. "Ask Contio about X" button pre-fills the question)

Example:

function generateAppDeepLink(appPath: string): string {
  return `https://app.contio.ai/open${appPath}`;
}

// Onboarding email CTAs
const calendarLink = generateAppDeepLink('/settings/calendars');
// https://app.contio.ai/open/settings/calendars

const inviteLink = generateAppDeepLink('/settings/users');
// https://app.contio.ai/open/settings/users

const chatLink = generateAppDeepLink('/?chat=new');
// https://app.contio.ai/open/?chat=new

const chatWithMessage = generateAppDeepLink(
  '/?chat=new&prefill=' + encodeURIComponent('Summarize my meetings')
);
// https://app.contio.ai/open/?chat=new&prefill=Summarize%20my%20meetings

const billingLink = generateAppDeepLink('/settings/billing');
// https://app.contio.ai/open/settings/billing

Session Requirements

Session-based deep links require users to have an active Contio session:

  • Browser Session: Valid JWT stored in browser cookies/localStorage
  • Desktop Session: Active authentication in the desktop application

If no session exists: - Web links (/m/{mtg-id}, /meetings/{mtg-id}) will redirect to login - Desktop links (contio://) will prompt for authentication in the desktop app

For users without existing sessions, use SSO Deep Links instead.


For SSO-enabled integrations, use the /p/{slug} flow to authenticate users and navigate them to specific locations in Contio. This method combines authentication with deep linking in a single flow.

Use SSO deep links when: - Your integration uses Partner SSO (OIDC/SAML) - Users need to authenticate before accessing Contio - You want to combine login and navigation in one step - You need co-branded landing pages

For users with existing sessions, consider using Session-Based Deep Links instead for a more direct experience.

Supported Targets

Target Description Use Case
web Redirect to Contio web app (default) Standard web-based access
desktop Open Contio desktop app at root General desktop app launch
meeting:{id} Open specific meeting in desktop Direct access to meeting notes/details
backlog Open backlog view in desktop Action item management

Web vs Desktop

The Contio web and desktop experiences are largely equivalent for viewing and managing meeting content. However, the desktop app is required for capturing meetings and generating notes — these features rely on local audio capture that isn't available in browsers.

For users who primarily view meeting notes and manage action items, the web experience is fully functional. For users who need to capture their own meetings, directing them to the desktop app ensures they have the complete feature set.

Landing Page as Download Hub

The Partner SSO landing page (/p/{slug}) serves as a convenient entry point where users can download the Contio desktop app if they don't have it installed. This makes it a good destination for onboarding new users who will need meeting capture capabilities.

Basic Usage

Web Target (Default)

If no target is specified, users are redirected to the Contio web application after authentication:

https://app.contio.ai/p/your-slug

This is equivalent to:

https://app.contio.ai/p/your-slug?target=web

Desktop Target

To launch the Contio desktop application after SSO:

https://app.contio.ai/p/your-slug?target=desktop

After successful authentication, the browser displays a callback page with a "Continue to Contio Desktop" button. Clicking this button triggers a deep link that opens the desktop app and signs the user in.

To open a specific meeting directly in the desktop app:

https://app.contio.ai/p/your-slug?target=meeting:550e8400-e29b-41d4-a716-446655440000

The meeting ID should be a valid UUID for a meeting the user has access to.

Example Implementation:

function openMeetingInContio(partnerSlug: string, meetingId: string, userEmail?: string) {
  const ssoUrl = new URL(`https://app.contio.ai/p/${partnerSlug}`);
  ssoUrl.searchParams.set('target', `meeting:${meetingId}`);
  ssoUrl.searchParams.set('auto', 'true');
  if (userEmail) {
    ssoUrl.searchParams.set('login_hint', userEmail);
  }

  window.open(ssoUrl.toString(), '_blank');
}

To open the action items backlog view directly:

https://app.contio.ai/p/your-slug?target=backlog

This is useful when your integration focuses on action item management.

Complete Example

Here's a complete example showing how to build SSO URLs with deep link targets:

interface DeepLinkOptions {
  partnerSlug: string;
  target: 'web' | 'desktop' | 'backlog' | `meeting:${string}`;
  autoRedirect?: boolean;
  loginHint?: string;
}

function buildContioSSOUrl(options: DeepLinkOptions): string {
  const url = new URL(`https://app.contio.ai/p/${options.partnerSlug}`);

  // Only add target if not 'web' (default)
  if (options.target !== 'web') {
    url.searchParams.set('target', options.target);
  }

  // Skip landing page UI if user is already authenticated in partner app
  if (options.autoRedirect) {
    url.searchParams.set('auto', 'true');
  }

  // Pre-fill email for faster IdP login
  if (options.loginHint) {
    url.searchParams.set('login_hint', options.loginHint);
  }

  return url.toString();
}

// Usage examples
const webUrl = buildContioSSOUrl({
  partnerSlug: 'acme',
  target: 'web'
});
// https://app.contio.ai/p/acme

const desktopUrl = buildContioSSOUrl({
  partnerSlug: 'acme',
  target: 'desktop',
  autoRedirect: true,
  loginHint: 'user@acme.com'
});
// https://app.contio.ai/p/acme?target=desktop&auto=true&login_hint=user@acme.com

const meetingUrl = buildContioSSOUrl({
  partnerSlug: 'acme',
  target: 'meeting:550e8400-e29b-41d4-a716-446655440000'
});
// https://app.contio.ai/p/acme?target=meeting:550e8400-e29b-41d4-a716-446655440000

const backlogUrl = buildContioSSOUrl({
  partnerSlug: 'acme',
  target: 'backlog',
  autoRedirect: true
});
// https://app.contio.ai/p/acme?target=backlog&auto=true

Desktop App Flow

When a desktop target is specified (desktop, meeting:{id}, or backlog), the authentication flow works as follows:

  1. User clicks SSO link with desktop target
  2. User authenticates with your IdP (if not already signed in)
  3. Browser redirects to Contio callback page
  4. Callback page displays "Continue to Contio Desktop" button
  5. Clicking the button triggers deep link: contio://auth/callback?...
  6. Contio desktop app opens, completes token exchange, and navigates to target
sequenceDiagram
    participant User
    participant PartnerApp as Partner App
    participant Browser
    participant IdP as Partner IdP
    participant ContioAPI as Contio API
    participant Desktop as Contio Desktop

    PartnerApp->>Browser: Open /p/{slug}?target=meeting:{id}
    Browser->>ContioAPI: Initiate SSO
    ContioAPI->>IdP: Redirect to authorize
    IdP-->>ContioAPI: Return auth code
    ContioAPI->>Browser: Redirect to callback page
    Browser->>Browser: Display "Continue to Desktop"
    User->>Browser: Click button
    Browser->>Desktop: Deep link: contio://auth/callback
    Desktop->>ContioAPI: Exchange code for tokens
    ContioAPI-->>Desktop: Access tokens
    Desktop->>Desktop: Navigate to /meetings/{id}

Fallback Handling

The callback page provides fallback options for users without the desktop app installed:

  • "Don't have Contio?" - Links to the desktop app download page
  • "Continue in browser" - Falls back to web app access

Your integration should consider these scenarios when designing the user experience.

Best Practices

Select the appropriate deep linking method based on your integration:

Scenario Recommended Approach Example
User has active Contio session Session-based deep link https://app.contio.ai/m/{mtg-id}
User needs to authenticate SSO deep link https://app.contio.ai/p/{slug}?target=meeting:{id}
Email/calendar notification Session-based landing page https://app.contio.ai/m/{mtg-id}
Web-only environment Direct web link https://app.contio.ai/meetings/{mtg-id}
Desktop app integration Desktop URL scheme contio://app/meetings/{mtg-id}
First-time user onboarding SSO deep link with desktop target https://app.contio.ai/p/{slug}?target=desktop

Use auto=true for Pre-Authenticated Users (SSO)

If users are already signed into your partner application, use auto=true to skip the landing page and reduce friction:

// User is already authenticated in partner app
const url = buildContioSSOUrl({
  partnerSlug: 'acme',
  target: 'meeting:abc123',
  autoRedirect: true,  // Skip landing page
  loginHint: currentUser.email  // Speed up IdP login
});

Validate Meeting IDs

Before constructing a meeting:{id} deep link, ensure the meeting ID is valid. Invalid or inaccessible meetings will show an error in the desktop app:

// Get meeting ID from your integration
const meetingId = await getMeetingIdFromContioAPI(userToken);

if (meetingId) {
  openMeetingInContio('acme', meetingId, user.email);
} else {
  // Fall back to backlog or desktop root
  openContioDesktop('acme', user.email);
}

Handle Missing Desktop App

Consider what happens if users don't have the Contio desktop app installed. The callback page handles this with download links, but you may want to:

  1. Check if desktop is likely installed (based on user preferences)
  2. Default to target=web if unsure
  3. Provide clear messaging about desktop app requirements

Troubleshooting

User Redirected to Login

If users are redirected to login when clicking /m/{mtg-id} or /meetings/{mtg-id}:

  1. Verify the user has an active Contio session
  2. Check that session cookies are not blocked
  3. Ensure the user has access to the meeting
  4. Consider using SSO deep links for unauthenticated users

If contio://app/meetings/{mtg-id} doesn't open the desktop app:

  1. Verify the desktop app is installed
  2. Check the URL scheme is correct for your environment:
  3. Production: contio://
  4. Beta/Staging: contio-beta://
  5. Try restarting the desktop app to re-register the URL scheme
  6. Fall back to /m/{mtg-id} landing page

Invalid Meeting ID

If you receive a "Meeting not found" error:

  • Verify the meeting ID is a valid UUID
  • Check that the meeting exists via the API
  • Ensure the user has access to the meeting
  • Confirm the meeting hasn't been deleted

If the SSO deep link doesn't open the desktop app:

  1. Verify the desktop app is installed
  2. Check that the contio:// URL scheme is registered
  3. Try restarting the desktop app
  4. Use "Continue in browser" as a fallback

Invalid Target Error

If you receive a validation error, ensure:

  • target is one of: web, desktop, backlog, or meeting:{uuid}
  • Meeting IDs are valid UUIDs (36 characters with dashes)
  • The target parameter is properly URL-encoded

Meeting Access Denied

If users can access the desktop app but not the meeting:

  • Verify the user has been granted access to the meeting
  • Check that the meeting ID is correct
  • Ensure the user's partner connection is still valid

Next Steps