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:
- Open Postman
- Click Import → Link
- 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:
- Click on the collection name
- Go to the Variables tab
- Edit the Current Value column as needed
- 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_emailmust belong to a Contio account. If not, sign up in the web app first. - Loopback redirect URI.
redirect_urimust behttp://127.0.0.1:PORTorhttp://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_emailvariable to your Contio account email - What happens: An OTP email is sent; the login
sessionis captured intootp_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_codeto 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
statefor 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
codeis captured intoauthorization_code - The returned
stateis verified againstoauth_state - Auto-captured:
authorization_code - If you get 401: Your
session_jwtis 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_tokenandrefresh_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:
- Generate a PAT from the Contio web app (Settings → API Tokens)
- In Postman, set the
oauth_tokenvariable to your PAT value - 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_uriis a loopback address (http://127.0.0.1:PORTorhttp://localhost:PORT) - Ensure you ran Step 3 first so
code_challengeandoauth_stateare populated - Verify
response_typeiscode
"insufficient_scope"¶
The token doesn't have the required scopes. This usually means:
- The requested scopes in
oauth_scopesdon'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_jwtis 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¶
- Authentication Guide — Implement OAuth 2.1 + PKCE in your application
- Personal Access Tokens — Use PATs for automation
- API Reference — Full endpoint documentation