Skip to content

Postman Collection Guide

The Contio MeetingOS User API includes a Postman collection with a fully scripted OAuth 2.1 + PKCE flow that lets you test the API without writing any code — and without a browser round-trip. You log in with an email one-time code, and the collection handles PKCE, authorization, and token exchange for you.

Getting the Collection

Download the Postman collection from the OpenAPI page, or import it directly:

  1. Open Postman
  2. Click ImportLink
  3. Enter: https://docs.contio.ai/user-api/openapi/user_postman_collection.json

Key Differences from Partner API

The User API uses OAuth 2.1 with PKCE instead of the Partner API's OAuth 2.0 flow:

Feature User API Partner API
Flow type Authorization Code + PKCE Authorization Code + OTP
Client secret Not required Required
Authentication Email OTP (scripted, no browser) Email OTP
Consent screen None (first-party auto-approve) N/A
Redirect URI Loopback only (127.0.0.1/localhost) Any registered URI
Token prefix cto_at_v1_ / cto_rt_v1_ Standard JWT
Refresh tokens Rotating (new token each refresh), valid 30 days Non-rotating

Setting Up Variables

The collection comes pre-configured with sensible defaults. In most cases, you only need to set user_email to the account you want tokens for:

Variable Default Description
user_email (empty) Set this. Email of the Contio account to log in as
oauth_scopes meetings:read meetings:write action-items:read action-items:write calendar:read workspace:read workspace:write Space-separated scopes to request
client_id YOUR_CLIENT_ID First-party OAuth client ID. Replace with the client ID issued for your first-party application.
redirect_uri http://127.0.0.1:53123/callback Loopback redirect URI — never actually visited, but must be a valid loopback address
baseUrl https://api.contio.ai Base URL for all requests (change for dev/stage)
otp_code (empty) The 6-digit code from your login email (set during the flow)

The following variables are captured automatically as you run the flow; you normally don't touch them: otp_session, session_jwt, oauth_token, refresh_token, code_verifier, code_challenge, oauth_state, authorization_code.

To modify variables:

  1. Click on the collection name
  2. Go to the Variables tab
  3. Edit the Current Value column as needed
  4. Click Save

About the client_id

The User API uses first-party OAuth — a flow designed for Contio's own applications (desktop app, CLI tools, etc.) to obtain tokens on behalf of a signed-in user.

Set client_id to the client ID issued for your first-party application. If you do not have a first-party client ID, use a Personal Access Token instead — set oauth_token to your PAT and skip the OAuth flow entirely.

How authentication works

  • The collection logs you in for you. Steps 1-2 send an email one-time code and exchange it for a session — you only need to paste the 6-digit code from your inbox.
  • No consent screen. First-party OAuth auto-approves for the signed-in user, so the authorize step returns the code immediately (no browser).
  • The account must already exist. The email in user_email must belong to a Contio account. If not, sign up in the web app first.
  • Loopback redirect URI. redirect_uri must be http://127.0.0.1:PORT or http://localhost:PORT. It is never actually visited — the code is read from the redirect header.

If the OAuth flow doesn't work for your use case, use a Personal Access Token instead — set oauth_token to your PAT and skip the flow entirely.

Available Scopes

Scope Description
meetings:read Read meetings, participants, agenda items, context
meetings:write Create/update/delete meetings and related resources
action-items:read Read action items
action-items:write Create/update/delete action items
calendar:read Read calendar events
workspace:read Read workspace settings and members
workspace:write Update workspace settings and manage members

Running the OAuth 2.1 + PKCE Flow

The collection includes a 🔐 OAuth 2.1 + PKCE Flow (Run in Order) folder with requests that walk you through the complete OAuth flow. Run them top to bottom.

Watch the Postman Console

Open the console (View → Show Postman Console) before you start. Every step logs what it captured and what to do next.

Step 1: Log In — Send OTP

Request: 1. Log In — Send OTP

Sends a 6-digit one-time code to user_email and starts a login session.

  • Before you run it: Set the user_email variable to your Contio account email
  • What happens: An OTP email is sent; the login session is captured into otp_session
  • Auto-captured: otp_session
  • If you get 404: That email has no Contio account — sign up in the web app first

Step 2: Log In — Verify OTP

Request: 2. Log In — Verify OTP

Verifies the code and completes login.

  • Before you run it: Set otp_code to the 6-digit code from your email
  • What happens: Returns your session JWT
  • Auto-captured: session_jwt (used as the Bearer token for the authorize step)

Already signed in?

If you already have a session JWT, set session_jwt directly and skip steps 1-2.

Step 3: Generate PKCE Parameters

Request: 3. Generate PKCE Parameters

Fetches the OIDC discovery document and generates the required PKCE parameters.

  • What happens:
  • Fetches the OpenID Connect discovery document
  • Generates a cryptographically secure code_verifier
  • Computes the S256 code_challenge
  • Generates a random state for CSRF protection
  • Auto-captured: code_verifier, code_challenge, oauth_state

Step 4: Authorize

Request: 4. Authorize (auto-captures code)

Calls /v1/oauth/authorize with your session JWT. Because first-party OAuth auto-approves, there is no consent screen — the endpoint returns a 302 redirect and the collection reads the authorization code straight from the Location header.

  • What happens:
  • Automatic redirect following is disabled so the 302 can be inspected
  • The code is captured into authorization_code
  • The returned state is verified against oauth_state
  • Auto-captured: authorization_code
  • If you get 401: Your session_jwt is missing or expired — re-run steps 1-2

Authorization codes expire quickly

Authorization codes typically expire within 10 minutes. Run the token exchange promptly.

Step 5: Exchange Token

Request: 5. Exchange Token (get access token)

Exchanges the authorization code + PKCE verifier for tokens.

  • What happens: Tokens are returned (no client secret needed!)
  • Auto-captured: oauth_token, refresh_token

OAuth flow complete!

After this step, you have valid tokens. The oauth_token variable is automatically used for all User API requests.

Step 6: Test API Call

Request: 6. Test API Call (verify token works)

Makes a sample API call to verify the token works.

  • What it does: Fetches your recent meetings
  • Expected result: 200 OK with meeting data (or empty array)

Step 7: Refresh Token (Optional)

Request: 7. Refresh Token (optional)

Use this to get a new access token when the current one expires.

  • When to use: Access tokens expire after 1 hour
  • Important: Refresh tokens rotate — each refresh returns a NEW refresh token and invalidates the old one
  • Lifetime: Refresh tokens are valid for 30 days, and each rotation resets that window — refreshing at least once every 30 days keeps the session alive
  • Auto-captured: New oauth_token and refresh_token

Step 8: Revoke Token (Optional)

Request: 8. Revoke Token (optional)

Revokes a token and its rotation chain.

  • What it does: Invalidates the specified token
  • Auth: Sends your session_jwt (this endpoint requires an authenticated user session)
  • Note: Always returns 200 per RFC 7009, even for unknown tokens

Using Personal Access Tokens (PAT)

For automation or when you don't want to use the OAuth flow, you can use a Personal Access Token:

  1. Generate a PAT from the Contio web app (Settings → API Tokens)
  2. In Postman, set the oauth_token variable to your PAT value
  3. Skip the OAuth flow and use any API endpoint directly

PATs are prefixed with cto_pat_v1_ and expire after a fixed period chosen at creation (30, 60, 90, 180, or 365 days), or when revoked.

See Personal Access Tokens for more details.

Troubleshooting

404 "Email not found" on Send OTP

The user_email has no Contio account. Sign up in the web app first, then re-run Step 1.

401 on Verify OTP

The code was wrong or expired. Re-run Step 1 to get a fresh code, then Verify with the new otp_code.

401 (no Location header) on Authorize

Your session_jwt is missing or expired. Re-run Steps 1-2 to log in again, then Step 3 and Step 4.

"Missing token parameter"

The oauth_token variable is empty. Run the OAuth flow first, or set a PAT.

"invalid_grant" on token exchange

  • The authorization code may have expired (codes expire quickly)
  • The PKCE verifier doesn't match the challenge
  • The redirect_uri doesn't match what was used in the authorize request

Solution: Re-run Steps 3-5 (generate fresh PKCE, authorize, exchange).

"invalid_request" on authorize

  • Check that redirect_uri is a loopback address (http://127.0.0.1:PORT or http://localhost:PORT)
  • Ensure you ran Step 3 first so code_challenge and oauth_state are populated
  • Verify response_type is code

"insufficient_scope"

The token doesn't have the required scopes. This usually means:

  • The requested scopes in oauth_scopes don't include what the endpoint needs
  • The user didn't approve all requested scopes

Solution: Re-run the OAuth flow with the correct scopes.

"401 Unauthorized" on API calls

  • The access token may have expired (1 hour lifetime)
  • Use the Refresh Token request to get a new access token
  • Or re-run the full OAuth flow

Tips

  • Run requests in order — Each step depends on the previous one
  • Check the Console — Postman logs helpful messages (View → Show Postman Console)
  • No browser needed — Login and authorization are fully scripted; you only paste the emailed OTP code
  • Variables are auto-saved — Tokens and codes are captured automatically by test scripts
  • Reuse your session — Steps 3-5 can be re-run without logging in again, as long as session_jwt is still valid
  • Use environments — Create separate environments for dev/staging/production (update baseUrl)
  • No client secret — PKCE replaces the need for a client secret

API Endpoints Overview

The collection includes all User API endpoints organized by category:

Category Endpoints Required Scope
Meetings List, Get, Create, Delete meetings:read / meetings:write
Meeting Participants List, Add, Remove meetings:read / meetings:write
Meeting Context List, Get, Upload, Download, Delete meetings:read / meetings:write
Action Items List, Create, Update, Delete action-items:read / action-items:write
Agenda Items List, Create, Update, Delete meetings:read / meetings:write
Calendar List Events, Get Event calendar:read
Workspace Get, Update, List Members, Update Role, Remove Member workspace:read / workspace:write
Workspace API Keys List, Delete workspace:read / workspace:write
Workspace Webhooks List, Delete, Re-enable workspace:read / workspace:write
User Tokens List, Delete (any valid scope)
User Events (SSE) Stream workspace events meetings:read

Next Steps