---
title: "List topics"
method: GET
path: "/topics"
tags: ["Topics"]
---

# List topics

`GET /topics`

## Request

- Base URL: `https://api.modem.dev/v1`
- URL: `https://api.modem.dev/v1/topics`
- Auth: HTTP bearer

List topics (issues) with filters, message counts, and authors. When embeddingSearch is provided, performs semantic search using vector similarity instead of keyword search. Semantic search finds topics by meaning, useful for queries like "users having trouble with authentication".

## Query parameters

- `view` 'v1' | 'v2': Deprecated and ignored. Topics are always served from the current pipeline, whichever value is sent. Accepted so existing requests keep working; omit it in new integrations.
- `search` string: Keyword search on title (max 100 chars). Wrap in double-quotes for exact token matching (e.g. "persona" matches the whole word and excludes "personal"). Ignored if embeddingSearch is provided.
- `embeddingSearch` string: Semantic search query using vector similarity. When provided, finds topics by meaning instead of keywords. Overrides the search parameter.
- `minSimilarity` number: Minimum cosine similarity threshold for embeddingSearch (0-1, higher = more similar). Default 0.7.
- `categories` string[]: Filter topics by keywords/categories (OR logic: topic must have ANY of the listed categories). Case-insensitive. For v2 topics a category is a catalog keyword slug (see topics.filterOptions), matched through the topic's open keyword attribution.
- `excludeCategories` string[]: Exclude topics by keywords/categories (OR logic: topic must have NONE of the listed categories). Case-insensitive. For v2 topics a category is a catalog keyword slug.
- `issueTypes` string[]
- `excludeIssueTypes` string[]
- `sources` string[]: Filter topics by message sources (OR logic: topic must have messages from ANY listed source). Case-insensitive; duplicates are ignored.
- `excludeSources` string[]: Exclude topics by message sources (OR logic: topic must have NO messages from ANY listed source). Case-insensitive; duplicates are ignored.
- `dateRange` object: Filter topics by time range overlap
  - `end` string, date-time, required
  - `start` string, date-time, required
- `sortBy` 'date' | 'groups' | 'lifecycle' | 'priority' | 'similarity': Sort order. 'groups' sorts by the number of groups. Use 'similarity' with embeddingSearch for best results.
- `sortOrder` 'asc' | 'desc'
- `priorities` string[]
- `excludePriorities` string[]
- `lifecycleStates` string[]: Filter topics by lifecycle state. "unknown" also matches topics with no lifecycle assessment.
- `companies` string[]: Filter topics by company IDs (OR logic: topic must have messages from people associated with ANY listed company).
- `excludeCompanies` string[]: Exclude topics by company IDs (OR logic: topic must have NO messages from people associated with ANY listed company).
- `products` union[]: Filter topics by product IDs (OR logic: topic must have messages in a channel mapped to ANY listed product). Pass "none" to also match topics with no product attribution at all.
  - union
    - string, uuid
    - 'none'
- `excludeProducts` union[]: Exclude topics by product IDs (OR logic: topic must have NO messages in a channel mapped to ANY listed product). Pass "none" to exclude topics with no product attribution at all.
  - union
    - string, uuid
    - 'none'
- `sourceContainers` string[]: Filter topics by source container IDs (OR logic: topic must draw evidence from ANY listed container). v2 only.
- `excludeSourceContainers` string[]: Exclude topics by source container IDs (OR logic: topic must draw evidence from NONE of the listed containers). v2 only.
- `persons` string[]: Filter topics by person IDs (OR logic: topic must have messages from ANY listed person).
- `excludePersons` string[]: Exclude topics by person IDs (OR logic: topic must have messages from NONE of the listed people).
- `ticketStatuses` string[]: Filter by linked ticket presence. "has_ticket" = has any linked ticket, "none" = no linked ticket.
- `excludeTicketStatuses` string[]: Exclude by linked ticket presence. "has_ticket" excludes topics with tickets, "none" excludes topics without tickets.
- `teamResponse` string[]: Filter by team response status. "not_responded" = no team member replied, "fully_responded" = team replied in all groups, "partially_responded" = team replied in some groups.
- `page` integer
- `limit` integer

## Response `200`

OK

- object
  - `data` object[], required
    - `authors` object[], required
      - `displayName` string, nullable, required: Optional display name for the author.
      - `id` union, required
        - string, uuid
        - string, uuid
      - `isBot` boolean, required: Whether the author is a bot account.
      - `sourceAuthorId` string, required: Author identifier in the source system.
      - `sourceAvatarUrl` string, uri, nullable, required: Avatar image URL from the source system.
      - `sourceName` string, required: Source system where the author originates.
    - `eventCount` integer, required: Number of events grouped under this topic.
    - `id` union, required
      - string, uuid
      - string, uuid
    - `issueType` 'bug_report' | 'complaint' | 'discussion' | 'feature_request' | 'praise', nullable, required: Classification for the topic as a type of issue.
    - `keywords` string[], required: Keywords associated with the topic.
    - `lifecycleState` 'completed' | 'dismissed' | 'in_progress' | 'open' | 'unknown', nullable, required: LLM-assessed lifecycle state for a topic.
    - `lifecycleStateConfidence` number, nullable, required: Confidence for the most recent lifecycle assessment.
    - `linkedTicket` object, nullable, required
      - `displayName` string, required
      - `linkType` 'issue' | 'project', required
      - `url` string, uri, required
    - `messageCount` number, required
    - `persons` object[], required
      - `avatarUrl` string, nullable, required
      - `company` object, nullable, required
        - `domain` string, nullable, required
        - `id` string, required
        - `isOrgCompany` boolean, required
        - `logoUrl` string, nullable, required
        - `name` string, required
      - `displayName` string, required
      - `id` string, required
      - `isBot` boolean, required
      - `isStaff` boolean, required
    - `priority` 'default' | 'high' | 'low' | 'very_high' | 'very_low', required: Priority level: very_low, low, default, high, or very_high
    - `similarity` number: Cosine similarity score (0-1, higher = more similar). Only present when embeddingSearch is used.
    - `sources` string[], required
    - `staffResponseGroupCount` number, required
    - `summary` string, required: Descriptive summary of the topic.
    - `timeRangeEnd` unknown
    - `timeRangeStart` unknown
    - `title` string, required: Short human-readable title of the topic.
    - `totalGroupCount` number, required
    - `updatedAt` string, date-time: Timestamp when the topic was last updated.
  - `limit` integer, required: The page size used for this response.
  - `page` integer, required: The 1-based page number returned.
  - `totalCount` integer, required: Total number of items matching the query, across all pages.

## Other responses

- `400`: Invalid request (validation failed).
- `401`: Missing or invalid API key.
- `403`: The API key does not have access to this resource.
- `404`: The requested resource was not found.
- `429`: Rate limit exceeded.
- `500`: Internal server error.

---

[API](https://skmtc.dev/modem/apis/modem-api.md) · [All operations](https://skmtc.dev/modem/apis/modem-api/llms.txt) · [OpenAPI document](https://skmtc.dev/modem/apis/modem-api/revisions/f889038a1048?raw)
