API Documentation

Convo API v1

Access your meeting data programmatically. Build integrations with Zapier, Make.com, or custom applications.

Quick Start

Get your first API response in under a minute.

1

Get your API key

API keys can only be created from the Convo desktop app, available for macOS and Windows. Open the app → Settings → API Keys → Create New Key. Copy the key — it's only shown once.

2

Make your first request

curl

curl -H "Authorization: Bearer convo_your_key_here" \ https://www.itsconvo.com/api/v1/user/profile

JavaScript

const res = await fetch("https://www.itsconvo.com/api/v1/user/profile", { headers: { Authorization: "Bearer convo_your_key_here" }, }); const { data } = await res.json(); console.log(data.subscription.tier);
3

See the response

{ "data": { "profile": { "name": "Alice Chen", "email": "alice@example.com" }, "subscription": { "tier": "professional", "status": "active" }, "apiUsage": { "aiGenerations": { "used": 12, "limit": 100, "remaining": 88 } } } }

That's it. Replace /user/profile with any endpoint below. Rate limit headers (X-RateLimit-Remaining) are included in every response.

Base URL

https://www.itsconvo.com

Response Format

All successful responses wrap results in a data key. All error responses use an error object with code and message fields.

Success

{ "data": { ... } }

Error

{ "error": { "code": "not_found", "message": "..." } }

The API is versioned at v1. New fields may be added to responses without a version bump — your code should tolerate unknown keys. Breaking changes will only ship in a new version with 90 days' notice.

Authentication

All API requests require a Bearer token in the Authorization header. See the Quick Start above to create your key and make your first request.

Python

import requests resp = requests.get("https://www.itsconvo.com/api/v1/conversations", headers={"Authorization": "Bearer convo_your_api_key_here"}) data = resp.json()["data"]

Key security

  • Keys are hashed on our servers — they cannot be retrieved after creation
  • Store keys in environment variables, never in source code
  • If a key is compromised, revoke it in Settings → API Keys and create a new one

Error responses

Missing or malformed header returns 401 unauthorized. A valid key on the Free plan returns 403 forbidden — API access requires Starter or above.

Tier Access

CapabilityStarterProfessionalEnterprise
API keys1310
Read endpoints
Write endpoints
AI generations10/month100/monthUnlimited
Webhooks3Unlimited
Rate limit100/hr500/hr2,000/hr

Rate Limits

Rate limits are enforced per user on a rolling hourly window. Every successful response includes rate limit headers:

ParameterTypeDefaultDescription
X-RateLimit-LimitintegerRequests allowed per hour for your tier
X-RateLimit-RemainingintegerRequests remaining in the current window
X-RateLimit-Resetunix timestampWhen the rate limit window resets

When exceeded, the API returns 429 with a Retry-After header indicating seconds until reset.

Endpoints

Conversations

GET/api/v1/conversations

List conversations for the authenticated user with pagination and search.

Query Parameters

ParameterTypeDefaultDescription
limitinteger20Max results (1–100)
offsetinteger0Results to skip
searchstringSearch by title
sinceISO 8601Return conversations after this date

Response

{ "data": [ { "id": "sess_a1b2c3", "title": "Q1 Planning Review", "startTime": "2026-03-18T14:00:00Z", "endTime": "2026-03-18T14:45:00Z", "duration": 45, "segmentCount": 128 } ], "pagination": { "total": 42, "limit": 20, "offset": 0 } }
GET/api/v1/conversations/{id}/transcript

Get the full transcript with speaker labels and timestamps.

Response

{ "data": { "id": "sess_a1b2c3", "segments": [ { "text": "Let's review the Q1 targets.", "speaker": "Alice", "timestamp": "2026-03-18T14:00:12Z" }, { "text": "Revenue is tracking at 92%.", "speaker": "Bob", "timestamp": "2026-03-18T14:00:25Z" } ] } }
GET/api/v1/conversations/{id}/keypoints

Get cached keypoints including sections, decisions, and action items. Returns 404 if not yet generated.

Response

{ "data": { "id": "sess_a1b2c3", "title": "Q1 Planning Review", "keypoints": { "sections": [{ "heading": "Revenue Update", "points": ["Tracking at 92% of target"] }], "decisions": ["Approved additional engineering hire"], "actionItems": [{ "item": "Send updated roadmap", "owner": "Sarah", "confidence": 0.9, "priority": "high" }], "participants": ["Alice", "Bob", "Sarah"], "importantDates": [{ "date": "2026-04-01", "context": "Q2 kickoff" }] }, "createdAt": "2026-03-18T15:00:00Z" } }
POST/api/v1/conversations/{id}/keypointsAI

Generate keypoints via AI. Returns cached result if available (no AI credit consumed). Use forceRefresh to regenerate.

Request Body

{ "forceRefresh": false }

Response is the same as GET with an additional cached boolean field.

GET/api/v1/conversations/{id}/feedback

Get cached communication feedback with scores, strengths, and growth areas. Returns 404 if not yet generated.

Response

{ "data": { "id": "sess_a1b2c3", "feedback": { "overallScore": 8.5, "categoryScores": { "clarity": 9, "listening": 8, "timeManagement": 7, "collaboration": 8, "decisionMaking": 9 }, "strengths": [{ "category": "Clarity", "description": "Clear articulation of goals", "timestamp": "14:05", "quote": "Let me summarize the three priorities..." }], "growthAreas": [{ "category": "Pacing", "description": "Spoke too quickly during technical sections", "suggestion": "Pause briefly between topics", "timestamp": "14:22" }], "talkListenRatio": 45, "actionPlan": ["Practice 2-second pauses between topics"] }, "overallScore": 8.5, "userSpeakerName": "Alice", "createdAt": "2026-03-18T15:02:00Z" } }
POST/api/v1/conversations/{id}/feedbackAI

Generate communication feedback via AI. Requires at least 10 transcript segments. Returns cached result if available.

Request Body

{ "forceRefresh": false }

Response is the same as GET with an additional cached boolean field.

POST/api/v1/conversations/{id}/queryAI

Ask a natural-language question about a conversation.

Request Body (required)

{ "query": "What were the main action items?" }

Response

{ "data": { "id": "sess_a1b2c3", "query": "What were the main action items?", "response": "Three action items were discussed: (1) Sarah will send the updated roadmap by Friday...", "metadata": { "segmentsAnalyzed": 128, "conversationDuration": 45 }, "suggestedQueries": ["Who is responsible for each task?", "What are the deadlines?"] } }

Query must be 500 characters or fewer.

POST/api/v1/conversations/{id}/emailAI

Generate a follow-up email based on the conversation.

Request Body

{ "recipientName": "Bob", "tone": "professional" }

Response

{ "data": { "id": "sess_a1b2c3", "subject": "Follow-up: Q1 Planning Review", "body": "Hi Bob,\n\nThank you for the productive meeting today...", "keyPoints": ["Revenue tracking at 92%", "New hire approved"], "actionItems": ["Sarah: Send updated roadmap by Friday"], "generatedAt": "2026-03-18T15:05:00Z" } }

Tone options: professional, casual, concise. All fields are optional.

POST/api/v1/conversations/{id}/share

Generate a public share URL for a conversation.

Response

{ "data": { "id": "sess_a1b2c3", "shareUrl": "https://www.itsconvo.com/shared/abc123" } }
PATCH/api/v1/conversations/{id}

Update a conversation title.

Request Body (required)

{ "title": "Updated Meeting Title" }

Response

{ "data": { "id": "sess_a1b2c3", "title": "Updated Meeting Title" } }
DELETE/api/v1/conversations/{id}

Soft-delete a conversation. Data can be recovered.

Response

{ "data": { "id": "sess_a1b2c3", "deleted": true } }

Calendar

GET/api/v1/calendar/events

List upcoming Google Calendar events. Requires Google Calendar connected in the Convo dashboard.

Query Parameters

ParameterTypeDefaultDescription
maxResultsinteger10Max events to return (1–50)
timeMinISO 8601Filter events after this time

User

GET/api/v1/user/profile

Get user profile, subscription tier, and API usage statistics.

Response

{ "data": { "profile": { "name": "Alice Chen", "email": "alice@example.com", "timezone": "America/New_York", "language": "en", "createdAt": "2025-09-15T10:30:00Z" }, "subscription": { "tier": "professional", "status": "active", "currentPeriodEnd": "2026-04-15T00:00:00Z" }, "apiUsage": { "aiGenerations": { "used": 34, "limit": 100, "remaining": 66, "resetsAt": "2026-04-01T00:00:00Z" } } } }

Enterprise tier returns null for limit and remaining (unlimited).

Webhooks

Webhooks deliver real-time event notifications to your server. Available to Professional and Enterprise tiers.

Events

conversation.createdconversation.updatedconversation.keypoints.readyconversation.summary.readyconversation.action_items.readyconversation.feedback.readyconversation.sharedconversation.deletedtranscript.readytranscript.failedwebhook.test

Event Payloads

Eventdata fields
conversation.createdconversationId
conversation.updatedconversationId, title
conversation.keypoints.readyconversationId, title
conversation.summary.readyconversationId, title, sectionCount
conversation.action_items.readyconversationId, actionItemCount
conversation.feedback.readyconversationId, overallScore
conversation.sharedconversationId, shareUrl
conversation.deletedconversationId
transcript.readyconversationId, segmentCount
transcript.failedconversationId, error
webhook.testmessage

Payload Signature

Payloads are signed with HMAC-SHA256 using the webhook secret. Verify the X-Convo-Signature header. Event type is in X-Convo-Event.

Payload Example

{ "event": "conversation.keypoints.ready", "data": { "conversationId": "sess_a1b2c3", "title": "Q1 Planning Review" }, "timestamp": "2026-03-19T14:30:00.000Z" }

Verify Signature (Node.js)

const crypto = require('crypto'); const signature = crypto .createHmac('sha256', webhookSecret) .update(rawBody) .digest('hex'); const isValid = signature === req.headers['x-convo-signature'];

Delivery Behavior

  • Webhooks are delivered with a 10-second timeout. Your endpoint must respond within this window.
  • Delivery is fire-and-forget — failed deliveries are not retried. Design your endpoint to return 200 quickly and process data asynchronously if needed.
  • To update a webhook's URL or events, delete the existing webhook and create a new one.
GET/api/v1/webhooks

List all active webhooks.

Response

{ "data": [{ "id": "wh_abc123", "url": "https://hooks.example.com/convo", "events": ["conversation.created"], "created_at": "2026-03-10T08:00:00Z" }] }
POST/api/v1/webhooks

Register a new webhook. HTTPS URLs only. The secret for HMAC verification is returned once on creation.

Request Body (required)

{ "url": "https://hooks.example.com/convo", "events": ["conversation.keypoints.ready", "conversation.feedback.ready"] }

Response

{ "data": { "id": "wh_abc123", "url": "https://hooks.example.com/convo", "events": ["conversation.keypoints.ready", "conversation.feedback.ready"], "secret": "whsec_a1b2c3d4e5f6g7h8i9j0klmnop", "createdAt": "2026-03-19T12:00:00Z" } }

Store the secret securely. It is only shown once.

DELETE/api/v1/webhooks

Delete a webhook by ID.

Request Body (required)

{ "id": "wh_abc123" }

Response

{ "data": { "id": "wh_abc123", "deleted": true } }
POST/api/v1/webhooks/test

Send a test event to a registered webhook to verify delivery. Returns the HTTP status code from your endpoint.

Request Body (required)

{ "webhookId": "wh_abc123" }

Response

{ "data": { "webhookId": "wh_abc123", "delivered": true, "statusCode": 200 } }

Sends a webhook.test event with a signed payload. Times out after 10 seconds.

Error Codes

StatusCodeDescription
400validation_errorInvalid request parameters or body
401unauthorizedMissing or invalid API key
403forbiddenInsufficient plan tier for this endpoint
404not_foundResource not found
429rate_limitedRate limit exceeded
429ai_limit_exceededMonthly AI generation limit reached
500internal_errorUnexpected server error

Error Response Format

{ "error": { "code": "not_found", "message": "Conversation not found" } }

Best Practices

Check cache before generating

Call GET /conversations/{id}/keypoints before POST. Cached results are free — POST uses an AI credit only when no cached result exists.

Handle rate limits with backoff

When you receive a 429, read the Retry-After header (seconds until reset) and wait before retrying. Avoid tight retry loops.

const res = await fetch(url, { headers }); if (res.status === 429) { const retryAfter = parseInt(res.headers.get("Retry-After") || "60", 10); await new Promise(r => setTimeout(r, retryAfter * 1000)); // retry the request }

Use webhooks instead of polling

Instead of polling GET /conversations for new data, register a webhook for conversation.keypoints.ready and react to events in real time. This is faster and doesn't count against your rate limit.

Store your API key securely

Use environment variables — never hardcode keys in source code or commit them to version control. If a key is compromised, revoke it immediately in Settings → API Keys and create a new one.

Paginate large result sets

The list conversations endpoint returns up to 100 results per page. Use offset to iterate through all results.

let offset = 0; const limit = 100; let allConversations = []; while (true) { const res = await fetch(`${BASE}/api/v1/conversations?limit=${limit}&offset=${offset}`, { headers }); const { data, pagination } = await res.json(); allConversations.push(...data); if (allConversations.length >= pagination.total) break; offset += limit; }