Otter.ai’s Public API provides programmatic access to retrieve channels, conversations, transcripts, audio, action items, insights, outlines, and workspace details from your Otter account.
API Fundamentals
Essential information for authenticating, paging through results, and understanding usage limits.
Authentication Create and manage your API keys
All API requests require authentication using Bearer token authentication. Follow the steps below to create your API key.
- Sign in to your Otter.ai account.
- Click Integrations in the left-side navigation. Navigate to the Developer tab.
-
Click Create key.
-
Click Copy and store the API key in a safe place.
Note: This is only visible once. Make sure you copy the API key in this pop-up. If you forget to copy, follow steps 1-3 to create another key. -
The API key can now be used. Follow steps 1-4 to create another API key.
Note: There is a limit of 2 API keys per user.
Using your API key:
Include your API key in the Authorization header for every request:
Authorization: Bearer YOUR_API_KEY
✅ Security best practices:
- Never share your API key publicly or commit it to version control
- Store API keys securely using environment variables or secrets management
- Rotate API keys periodically
Rate Limits
Enterprise plan users are currently limited to 10 requests / second. If you exceed your rate limit, you'll receive a 429 Too Many Requests response.
Pagination
List endpoints use cursor-based pagination for efficient data retrieval.
Pagination Response
{
"meta": {
"retrieved_at": "2025-07-31T12:00:00Z",
"has_more": true,
"next_cursor": "next_cursor_position"
},
"data": [ /* array of results */ ]
}
Meta Fields
| Field | Type | Description |
|---|---|---|
retrieved_at |
string | Timestamp when data was retrieved (ISO 8601 format) |
has_more |
boolean | Whether more pages are available |
next_cursor |
string (optional) | Cursor for the next page |
Usage
To retrieve the next page, use the next_cursor value in your next request's cursor query parameter:
GET /conversations?cursor=next_cursor_position&limit=20
Continue paginating until has_more is false.
Webhooks
Webhooks are the recommended way to build export integrations with Otter. Instead of constantly polling the API to check for new conversations or action items, webhooks push real-time notifications to your application the moment events occur. This makes webhooks ideal for automatically syncing meeting summaries to your CRM, sending action items to project management tools, or triggering custom workflows whenever a transcript is ready. By using webhooks, you'll build more efficient integrations that respond instantly to changes while staying well within API rate limits.
Endpoints
Explore the available API endpoints, grouped by type.
Channel Endpoints for retrieving channel data
A Channel lets you organize Conversations.
GET /channels
Use this endpoint to list channels for the authenticated user. Results are returned in alphabetical order by channel name.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | No | Returns all channels that the user is a member of. Pagination parameters are not applicable to this endpoint. |
cursor |
string | No | Cursor for pagination |
Example Request:
curl -X GET "https://api.otter.ai/v1/channels" \ -H "Authorization: Bearer YOUR_API_KEY"
Response: Returns a ChannelListResponse with channel data.
- meta: Response metadata, including retrieved_at
- data: An array of channel objects
{
"meta": {
"retrieved_at": "2025-07-31T12:00:00Z"
},
"data": [
{
"id": "channel_id",
"name": "backend product meeting",
"member_count": 50,
"owner": {
"id": "user_id",
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe",
"email": "Jane@test.com"
}
}
]
}
Channel object
| Field | Type | Description |
| id | string | Unique channel identifier |
| name | string | Name of the channel |
| member_count | integer | Number of members in the channel |
| owner | User | Owner of the channel |
Error Response(s):
| Status | Description |
| 400 | Invalid request parameters |
Conversations Endpoints to create, list, and retrieve conversations, including conversation details and audio downloads
POST /conversations
Creates a new conversation from a file. This is useful if you are importing calls into Otter, such as from a Dialer.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
file |
string (URL) | Yes | URL to the file to process |
name |
string | No | Name for the conversation |
Example Request:
curl -X POST "https://api.otter.ai/v1/conversations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file": "https://example.com/file.mp4",
"name": "Product Launch Meeting"
}'
Response: Returns a ConversationCreateResponse with status.
{
"status": "success",
"completed_at": "2025-12-01 01:00:00Z",
"file": "audio.mp3"
}
GET /conversations
Use this endpoint to list conversations for the authenticated user. Results are returned in reverse chronological order (most recent first) and use cursor-based pagination for efficient retrieval. You can optionally include shared conversations or filter results by channel.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| include_shared | boolean | No | Whether to include conversations shared with the user. Default: false. Automatically set to true if channel_id is provided |
| channel_id | string | No | Filter conversations by channel ID. Overrides include_shared |
| limit | integer | No | Number of items to return per page. Minimum: 1, Maximum: 100 |
| cursor | string | No | Cursor for pagination. Use the next_cursor value from the previous response to retrieve the next page |
Example Request:
curl -X GET "https://api.otter.ai/v1/conversations?include_shared=false&channel_id=&limit=20&cursor=" \ -H "Authorization: Bearer YOUR_API_KEY"
Response: Returns a ConversationListResponse with conversation data and pagination metadata.
- meta: Pagination metadata, including retrieved_at, has_more, and next_cursor
- data: An array of conversation objects
{
"meta": {
"retrieved_at": "2025-07-31T12:00:00Z",
"has_more": true,
"next_cursor": "next_cursor_position"
},
"data": [
{
"id": "conversation_id",
"title": "product launch meeting",
"url": "https://otter.ai/u/conversation_id",
"owner": {
"id": "user_id",
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe",
"email": "Jane@test.com"
},
"created_at": "2025-07-31T12:00:00Z",
"process_status": {
"abstract_summary": null,
"action_item": null,
"outline": null
},
"calendar_guests": [
{
"name": "John Doe",
"email": "john@test.com"
}
],
"shared_emails": [
{
"email": "hello@example.com",
"user": {
"id": "user_id",
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe",
"email": "Jane@test.com"
},
"permission": "collaborate"
}
],
"shared_channels": [
{
"channel": {
"id": "channel_id",
"name": "backend product meeting",
"member_count": 50,
"owner": {
"id": "user_id",
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe",
"email": "Jane@test.com"
}
},
"permission": "collaborate"
}
],
"abstract_summary": "This meeting discussed the next steps in the project launch",
"conf_join_url": "https://zoom.us/j/1234567890"
}
]
}
Pagination
- has_more: Indicates whether additional results are available
- next_cursor: Use this value in the next request to retrieve the next page
Conversation object
| Field | Type | Description |
| id | string | Unique conversation identifier |
| title | string | Title of the conversation |
| url | string | URL to view the conversation in Otter |
| owner | User | Owner of the conversation |
| created_at | string | Timestamp when the conversation was created |
| process_status | object | Processing status for generated data such as summary, action items, and outline |
| calendar_guests | array | List of calendar guests associated with the conversation |
| shared_emails | array | List of users or email addresses the conversation is shared with |
| shared_channels | array | List of channels the conversation is shared with |
| abstract_summary | string | Generated summary of the conversation |
| conf_join_url | string | Conferencing join URL associated with the conversation |
Error Responses:
| Status | Description |
| 400 | Invalid filter or pagination parameters |
| 404 | Channel not found |
GET /conversations/{id}
Use this endpoint to get the summary and details of a specific conversation. You can optionally include additional conversation data such as action items, insights, outlines, transcript, or all available relationships.
Path Parameters:
| Parameter | Type | Required | Description |
| id | string | Yes | Conversation ID |
Query Parameters:
| Parameter | Type | Required | Description |
| include | string | Yes | Comma-separated list of additional data to include. Options: action_items, insights, outlines, transcript, all. If all is specified, all available relationship fields are returned. Example: insights,transcript
|
Example Request:
curl -X GET "https://api.otter.ai/v1/conversations/{id}?include=action_items" \
-H "Authorization: Bearer YOUR_API_KEY"
-
Response: Returns a
ConversationResponsewith conversation details and requested relationships.- meta: Response metadata, including retrieved_at
- data: The conversation object
- relationships: Additional related data returned when requested with the include parameter
{ "meta": { "retrieved_at": "2025-07-31T12:00:00Z" }, "data": { "relationships": { "action_items": [ { "id": "action_item_id", "text": "Follow up with the sales team", "assignee": { "id": "user_id", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "email": "Jane@test.com" }, "status": { "completed": true, "created_at": "2025-07-31T12:00:00Z", "last_modified_at": "2025-07-31T12:00:00Z", "completed_at": "2025-07-31T12:00:00Z" } } ], "insights": [ { "topic": "Decisions", "text": [ [ "Launch next week", "Prepare for marketing" ] ] } ], "outline": [ { "section": "Project risks", "text": [ "Team fatigue", "Tight deadline", "Dependency on external API" ] } ], "transcript": { "content": "Sam 00:15 \\n Welcome to project launch meeting!\\n", "format": "txt" }, "custom_prompt": { "label": "Prompt created by user", "output": "The product launch meeting was successful." } }, "id": "conversation_id", "title": "product launch meeting", "url": "https://otter.ai/u/conversation_id", "owner": { "id": "user_id", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "email": "Jane@test.com" }, "created_at": "2025-07-31T12:00:00Z", "process_status": { "abstract_summary": null, "action_item": null, "outline": null }, "calendar_guests": [ { "name": "John Doe", "email": "john@test.com" } ], "shared_emails": [ { "email": "hello@example.com", "user": { "id": "user_id", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "email": "Jane@test.com" }, "permission": "collaborate" } ], "shared_channels": [ { "channel": { "id": "channel_id", "name": "backend product meeting", "member_count": 50, "owner": { "id": "user_id", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "email": "Jane@test.com" } }, "permission": "collaborate" } ], "abstract_summary": "This meeting discussed the next steps in the project launch", "conf_join_url": "https://zoom.us/j/1234567890" } }
Example Request:
curl -X GET "https://api.otter.ai/v1/conversations/conversation_id?include=all" \ -H "Authorization: Bearer YOUR_API_KEY"
-
Response: Returns a
ConversationResponsewith conversation details and requested relationships.- meta: Response metadata, including retrieved_at
- data: The conversation object
- relationships: Additional related data returned when requested with the include parameter
{ "meta": { "retrieved_at": "2025-10-05T12:00:00Z" }, "data": { "id": "conversation_id", "title": "Customer Discovery Call – ACME Corp", "url": "https://otter.ai/u/conversation_id", "owner": { "id": "owner_id", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com" }, "created_at": "2025-10-05T11:55:00Z", "process_status": { "abstract_summary": "finished", "action_item": "finished", "outline": "finished" }, "calendar_guests": null, "shared_emails": [], "shared_channels": [ { "channel": { "id": "channel_id", "name": "All customer calls", "member_count": 25, "owner": { "id": "channel_owner_id", "name": "John Smith", "first_name": "John", "last_name": "Smith", "email": "john.smith@example.com" } }, "permission": "collaborate" } ], "abstract_summary": "The team met with ACME Corp to confirm their requirements, discuss pricing options, and align on an evaluation timeline for adopting Otter.ai across their go-to-market team.", "conf_join_url": "https://zoom.us/j/00000000000", "relationships": { "action_items": [ { "id": "action_item_id_1", "text": "Send follow-up email with pricing summary and implementation overview.", "assignee": { "id": "owner_id", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com" }, "status": null }, { "id": "action_item_id_2", "text": "ACME to confirm final user count and preferred contract term.", "assignee": { "id": "customer_contact_id", "name": "Alex Taylor", "first_name": "Alex", "last_name": "Taylor", "email": "alex.taylor@example.com" }, "status": null } ], "insights": [ { "topic": "Budget", "text": [ "ACME has a preliminary budget in place and is comfortable with a per-seat model as long as usage is clear.", "They are open to a flat-rate option if it simplifies internal approvals." ] }, { "topic": "Authority", "text": [ "Alex Taylor is the main champion, but final approval will come from the VP of Operations.", "Security and procurement teams will review the proposal before signature." ] }, { "topic": "Need", "text": [ "ACME needs automated call summaries for customer meetings and better visibility into team activity.", "They want to reduce manual note-taking and ensure consistent follow-up on action items." ] }, { "topic": "Timeline", "text": [ "They aim to complete evaluation this month and go live at the start of next quarter.", "Next internal decision checkpoint is scheduled for next week." ] } ], "outlines": [ { "section": "Introductions and Context", "text": [ "Participants introduced themselves and clarified roles.", "ACME shared context on their current workflow and challenges with manual note-taking." ] }, { "section": "Pricing and Rollout Options", "text": [ "The team reviewed per-seat and flat-rate pricing options.", "They discussed rollout plans starting with key go-to-market teams and expanding later." ] } ], "transcript": { "content": "Jane Doe 00:00\nThanks everyone for joining today. I’d love to understand how your team handles customer calls and where Otter might help.\n\nAlex Taylor 00:07\nRight now we take notes manually, and we often miss details or lose track of follow-ups after the meeting.\n\nJane Doe 00:14\nThat makes sense. Otter can automatically capture the conversation, generate summaries, and highlight key action items.\n\nAlex Taylor 00:21\nThat would be really valuable for us, especially for onboarding new reps and improving consistency.\n\nJane Doe 00:28\nGreat—I'll send a follow-up with pricing options and a proposed rollout timeline.\n\nAlex Taylor 00:35\nSounds good. We'll review internally and get back to you this week.", "format": "txt" }, "custom_prompt": null } } }
Conversation object
| Field | Type | Description |
| id | string | Unique conversation identifier |
| title | string | Title of the conversation |
| url | string | URL to view the conversation in Otter |
| owner | User | Owner of the conversation |
| created_at | string | Timestamp when the conversation was created |
| process_status | object | Processing status for generated data such as summary, action items, and outline |
| calendar_guests | array | List of calendar guests associated with the conversation |
| shared_emails | array | List of users or email addresses the conversation is shared with |
| shared_channels | array | List of channels the conversation is shared with |
| abstract_summary | string | Generated summary of the conversation |
| conf_join_url | string | Conferencing join URL associated with the conversation |
| relationships | object | Additional related data returned when requested with the include parameter |
Error responses:
| Status | Description |
| 404 | Conversation not found |
GET /conversations/{id}/audio
Use this endpoint to get the MP3 audio download link for a specific conversation.
Path Parameters:
| Parameter | Type | Required | Description |
| id | string | Yes | Conversation ID |
Example Request:
curl -X GET "https://api.otter.ai/v1/conversations/{id}/audio" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
Returns an AudioResponse containing the MP3 audio download link.
- meta: Response metadata, including retrieved_at
- data: The audio object
{
"meta": {
"retrieved_at": "2025-07-31T12:00:00Z"
},
"data": {
"url": "https://test.com/audio.mp3"
}
}
Audio Object:
| Field | Type | Description |
| url | string | Download URL for the MP3 audio file |
Error Response:
| Status | Description |
| 404 | Conversation not found |
Workspace Endpoints to access workspace information, including details, and members
GET /workspace
Use this endpoint to get the workspace for the authenticated user. The response includes workspace details such as the workspace ID, name, owner, member count, handle, and type.
Example Request:
curl -X GET "https://api.otter.ai/v1/workspace" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
Returns a WorkspaceGetResponse containing the authenticated user’s workspace details.
- meta: Response metadata, including retrieved_at
- data: The authenticated user’s workspace object
{
"meta": {
"retrieved_at": "2025-07-31T12:00:00Z"
},
"data": {
"id": 42,
"name": "workspace name",
"owner": {
"id": "user_id",
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe",
"email": "Jane@test.com"
},
"member_count": 50,
"handle": "otter.ai",
"type": "business"
}
}
Workspace object:
| Field | Type | Description |
| id | integer | Unique workspace identifier |
| name | string | Name of the workspace |
| owner | User | Owner of the workspace |
| member_count | integer | Number of members in the workspace |
| handle | string | Workspace handle (e.g., domain or identifier like otter.ai) |
| type | string | Type of workspace (e.g., business) |
Error responses:
| Status | Description |
| 404 | User not in a workspace |
👉 Best Practices
Rate Limiting
Implement appropriate rate limiting in your application to avoid overwhelming the API. Consider implementing exponential backoff for retries.
Error Handling
Always check for and handle error responses gracefully. Parse the error details to provide meaningful feedback to users.
Pagination
Use cursor-based pagination for large result sets. Don't attempt to retrieve all data in a single request.
Selective Loading
Use the include parameter in conversation endpoints to fetch only the data you need. This reduces response payload size and improves performance.
Caching
Cache responses where appropriate to reduce API calls. Consider implementing a caching layer for frequently accessed data.
Field Selection
When using the include parameter, only request the fields you actually need rather than using all
Feedback
0 comments
Article is closed for comments.