openapi: 3.1.0 info: title: Discourse API Documentation Admin Topics API x-logo: url: https://docs.discourse.org/logo.svg version: latest description: 'This page contains the documentation on how to use Discourse through API calls. > Note: For any endpoints not listed you can follow the [reverse engineer the Discourse API](https://meta.discourse.org/t/-/20576) guide to figure out how to use an API endpoint. ### Request Content-Type The Content-Type for POST and PUT requests can be set to `application/x-www-form-urlencoded`, `multipart/form-data`, or `application/json`. ### Endpoint Names and Response Content-Type Most API endpoints provide the same content as their HTML counterparts. For example the URL `/categories` serves a list of categories, the `/categories.json` API provides the same information in JSON format. Instead of sending API requests to `/categories.json` you may also send them to `/categories` and add an `Accept: application/json` header to the request to get the JSON response. Sending requests with the `Accept` header is necessary if you want to use URLs for related endpoints returned by the API, such as pagination URLs. These URLs are returned without the `.json` prefix so you need to add the header in order to get the correct response format. ### Authentication Some endpoints do not require any authentication, pretty much anything else will require you to be authenticated. To become authenticated you will need to create an API Key from the admin panel. Once you have your API Key you can pass it in along with your API Username as an HTTP header like this: ``` curl -X GET "http://127.0.0.1:3000/admin/users/list/active.json" \ -H "Api-Key: 714552c6148e1617aeab526d0606184b94a80ec048fc09894ff1a72b740c5f19" \ -H "Api-Username: system" ``` and this is how POST requests will look: ``` curl -X POST "http://127.0.0.1:3000/categories" \ -H "Content-Type: multipart/form-data;" \ -H "Api-Key: 714552c6148e1617aeab526d0606184b94a80ec048fc09894ff1a72b740c5f19" \ -H "Api-Username: system" \ -F "name=89853c20-4409-e91a-a8ea-f6cdff96aaaa" \ -F "color=49d9e9" \ -F "text_color=f0fcfd" ``` ### Boolean values If an endpoint accepts a boolean be sure to specify it as a lowercase `true` or `false` value unless noted otherwise. ' license: name: MIT url: https://docs.discourse.org/LICENSE.txt servers: - url: https://{defaultHost} variables: defaultHost: default: discourse.example.com tags: - name: Topics paths: /posts.json: post: summary: Creates a new topic, a new post, or a private message tags: - Topics operationId: createTopicPostPM parameters: [] responses: '200': description: post created content: application/json: schema: additionalProperties: false properties: id: type: integer name: type: - string - 'null' username: type: string avatar_template: type: string created_at: type: string raw: type: string cooked: type: string post_number: type: integer post_type: type: integer posts_count: type: integer updated_at: type: string reply_count: type: integer reply_to_post_number: type: - string - 'null' quote_count: type: integer incoming_link_count: type: integer reads: type: integer readers_count: type: integer score: type: number yours: type: boolean topic_id: type: integer topic_slug: type: string display_username: type: - string - 'null' primary_group_name: type: - string - 'null' flair_name: type: - string - 'null' flair_url: type: - string - 'null' flair_bg_color: type: - string - 'null' flair_color: type: - string - 'null' flair_group_id: type: - integer - 'null' badges_granted: type: array items: {} version: type: integer can_edit: type: boolean can_delete: type: boolean can_recover: type: boolean can_see_hidden_post: type: boolean can_wiki: type: boolean user_title: type: - string - 'null' bookmarked: type: boolean actions_summary: type: array items: type: object additionalProperties: false properties: id: type: integer can_act: type: boolean required: - id - can_act moderator: type: boolean admin: type: boolean staff: type: boolean user_id: type: integer draft_sequence: type: integer hidden: type: boolean trust_level: type: integer deleted_at: type: - string - 'null' user_deleted: type: boolean edit_reason: type: - string - 'null' can_view_edit_history: type: boolean wiki: type: boolean reviewable_id: type: - integer - 'null' reviewable_score_count: type: integer reviewable_score_pending_count: type: integer post_url: type: string post_localizations: type: array items: {} mentioned_users: type: array items: {} required: - id - name - username - avatar_template - created_at - cooked - post_number - post_type - posts_count - updated_at - reply_count - reply_to_post_number - quote_count - incoming_link_count - reads - readers_count - score - yours - topic_id - topic_slug - display_username - primary_group_name - flair_name - flair_url - flair_bg_color - flair_color - version - can_edit - can_delete - can_recover - can_wiki - user_title - bookmarked - actions_summary - moderator - admin - staff - user_id - draft_sequence - hidden - trust_level - deleted_at - user_deleted - edit_reason - can_view_edit_history - wiki - reviewable_id - reviewable_score_count - reviewable_score_pending_count - post_url requestBody: content: application/json: schema: additionalProperties: false properties: title: type: string description: Required if creating a new topic or new private message. raw: type: string topic_id: type: integer description: Required if creating a new post. category: type: integer description: 'Optional if creating a new topic, and ignored if creating a new post.' target_recipients: type: string description: Required for private message, comma separated. example: blake,sam target_usernames: type: string description: Deprecated. Use target_recipients instead. deprecated: true archetype: type: string description: Required for new private message. example: private_message created_at: type: string reply_to_post_number: type: integer description: Optional, the post number to reply to inside a topic. embed_url: type: string description: 'Provide a URL from a remote system to associate a forum topic with that URL, typically for using Discourse as a comments system for an external blog.' external_id: type: string description: 'Provide an external_id from a remote system to associate a forum topic with that id.' auto_track: type: boolean description: 'If false, the user will not track the topic. By default, the user will track the topic.' required: - raw /t/{id}/posts.json: get: summary: Get specific posts from a topic tags: - Topics operationId: getSpecificPostsFromTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: specific posts content: application/json: schema: type: object properties: post_stream: type: object properties: posts: type: array items: type: object properties: id: type: integer name: type: - string - 'null' username: type: string avatar_template: type: string created_at: type: string cooked: type: string post_number: type: integer post_type: type: integer updated_at: type: string reply_count: type: integer reply_to_post_number: type: - string - 'null' quote_count: type: integer incoming_link_count: type: integer reads: type: integer readers_count: type: integer score: type: number yours: type: boolean topic_id: type: integer topic_slug: type: string display_username: type: - string - 'null' primary_group_name: type: - string - 'null' flair_name: type: - string - 'null' flair_url: type: - string - 'null' flair_bg_color: type: - string - 'null' flair_color: type: - string - 'null' version: type: integer can_edit: type: boolean can_delete: type: boolean can_recover: type: boolean can_wiki: type: boolean read: type: boolean user_title: type: - string - 'null' actions_summary: type: array items: type: object properties: id: type: integer can_act: type: boolean moderator: type: boolean admin: type: boolean staff: type: boolean user_id: type: integer hidden: type: boolean trust_level: type: integer deleted_at: type: - string - 'null' user_deleted: type: boolean edit_reason: type: - string - 'null' can_view_edit_history: type: boolean wiki: type: boolean reviewable_id: type: integer reviewable_score_count: type: integer reviewable_score_pending_count: type: integer id: type: integer requestBody: content: application/json: schema: type: object properties: post_ids[]: type: integer required: - post_ids[] /t/{id}.json: get: summary: Get a single topic tags: - Topics operationId: getTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: specific posts content: application/json: schema: additionalProperties: false properties: post_stream: type: object additionalProperties: false properties: posts: type: array items: type: object additionalProperties: false properties: id: type: integer name: type: string username: type: string avatar_template: type: string created_at: type: string cooked: type: string post_number: type: integer post_type: type: integer updated_at: type: string reply_count: type: integer reply_to_post_number: type: - string - 'null' quote_count: type: integer incoming_link_count: type: integer reads: type: integer readers_count: type: integer score: type: number yours: type: boolean topic_id: type: integer topic_slug: type: string display_username: type: string primary_group_name: type: - string - 'null' flair_name: type: - string - 'null' flair_url: type: - string - 'null' flair_bg_color: type: - string - 'null' flair_color: type: - string - 'null' version: type: integer can_edit: type: boolean can_delete: type: boolean can_recover: type: boolean can_see_hidden_post: type: boolean can_wiki: type: boolean link_counts: type: array items: type: object additionalProperties: false properties: url: type: string internal: type: boolean reflection: type: boolean title: type: string clicks: type: integer required: - url - internal - reflection - title - clicks read: type: boolean user_title: type: - string - 'null' bookmarked: type: boolean actions_summary: type: array items: type: object additionalProperties: false properties: id: type: integer can_act: type: boolean required: - id - can_act moderator: type: boolean admin: type: boolean staff: type: boolean user_id: type: integer hidden: type: boolean trust_level: type: integer deleted_at: type: - string - 'null' user_deleted: type: boolean edit_reason: type: - string - 'null' can_view_edit_history: type: boolean wiki: type: boolean reviewable_id: type: integer reviewable_score_count: type: integer reviewable_score_pending_count: type: integer required: - id - name - username - avatar_template - created_at - cooked - post_number - post_type - updated_at - reply_count - reply_to_post_number - quote_count - incoming_link_count - reads - readers_count - score - yours - topic_id - topic_slug - display_username - primary_group_name - flair_name - flair_url - flair_bg_color - flair_color - version - can_edit - can_delete - can_recover - can_wiki - link_counts - read - user_title - bookmarked - actions_summary - moderator - admin - staff - user_id - hidden - trust_level - deleted_at - user_deleted - edit_reason - can_view_edit_history - wiki - reviewable_id - reviewable_score_count - reviewable_score_pending_count stream: type: array items: {} required: - posts - stream timeline_lookup: type: array items: {} suggested_topics: type: array items: type: object additionalProperties: false properties: id: type: integer title: type: string fancy_title: type: string slug: type: string posts_count: type: integer reply_count: type: integer highest_post_number: type: integer image_url: type: - string - 'null' created_at: type: string last_posted_at: type: - string - 'null' bumped: type: boolean bumped_at: type: string archetype: type: string unseen: type: boolean pinned: type: boolean unpinned: type: - string - 'null' excerpt: type: string visible: type: boolean closed: type: boolean archived: type: boolean bookmarked: type: - string - 'null' liked: type: - string - 'null' tags: type: array items: type: object properties: id: type: integer name: type: string slug: type: string required: - id - name - slug tags_descriptions: type: object additionalProperties: false properties: {} like_count: type: integer views: type: integer category_id: type: integer featured_link: type: - string - 'null' posters: type: array items: type: object additionalProperties: false properties: extras: type: string description: type: string user: type: object additionalProperties: false properties: id: type: integer username: type: string name: type: string avatar_template: type: string required: - id - username - name - avatar_template required: - extras - description - user required: - id - title - fancy_title - slug - posts_count - reply_count - highest_post_number - image_url - created_at - last_posted_at - bumped - bumped_at - archetype - unseen - pinned - unpinned - excerpt - visible - closed - archived - bookmarked - liked - tags - tags_descriptions - like_count - views - category_id - featured_link - posters tags: type: array items: type: object properties: id: type: integer name: type: string slug: type: string required: - id - name - slug tags_descriptions: type: object additionalProperties: false properties: {} id: type: integer title: type: string fancy_title: type: string posts_count: type: integer created_at: type: string views: type: integer reply_count: type: integer like_count: type: integer last_posted_at: type: - string - 'null' visible: type: boolean closed: type: boolean archived: type: boolean has_summary: type: boolean archetype: type: string slug: type: string category_id: type: integer word_count: type: - integer - 'null' deleted_at: type: - string - 'null' user_id: type: integer featured_link: type: - string - 'null' pinned_globally: type: boolean pinned_at: type: - string - 'null' pinned_until: type: - string - 'null' image_url: type: - string - 'null' slow_mode_seconds: type: integer draft: type: - string - 'null' draft_key: type: string draft_sequence: type: integer unpinned: type: - string - 'null' pinned: type: boolean current_post_number: type: integer highest_post_number: type: - integer - 'null' deleted_by: type: - string - 'null' has_deleted: type: boolean actions_summary: type: array items: type: object additionalProperties: false properties: id: type: integer count: type: integer hidden: type: boolean can_act: type: boolean required: - id - count - hidden - can_act chunk_size: type: integer bookmarked: type: boolean bookmarks: type: array items: {} topic_timer: type: - string - 'null' message_bus_last_id: type: integer participant_count: type: integer show_read_indicator: type: boolean thumbnails: type: - string - 'null' slow_mode_enabled_until: type: - string - 'null' details: type: object additionalProperties: false properties: can_edit: type: boolean notification_level: type: integer can_move_posts: type: boolean can_delete: type: boolean can_remove_allowed_users: type: boolean can_create_post: type: boolean can_reply_as_new_topic: type: boolean can_invite_to: type: boolean can_invite_via_email: type: boolean can_flag_topic: type: boolean can_convert_topic: type: boolean can_review_topic: type: boolean can_close_topic: type: boolean can_archive_topic: type: boolean can_split_merge_topic: type: boolean can_edit_staff_notes: type: boolean can_toggle_topic_visibility: type: boolean can_pin_unpin_topic: type: boolean can_banner_topic: type: boolean can_moderate_category: type: boolean can_remove_self_id: type: integer participants: type: array items: type: object additionalProperties: false properties: id: type: integer username: type: string name: type: string avatar_template: type: string post_count: type: integer primary_group_name: type: - string - 'null' flair_name: type: - string - 'null' flair_url: type: - string - 'null' flair_color: type: - string - 'null' flair_bg_color: type: - string - 'null' flair_group_id: type: - integer - 'null' admin: type: boolean moderator: type: boolean trust_level: type: integer required: - id - username - name - avatar_template - post_count - primary_group_name - flair_name - flair_url - flair_color - flair_bg_color - admin - moderator - trust_level created_by: type: object additionalProperties: false properties: id: type: integer username: type: string name: type: string avatar_template: type: string required: - id - username - name - avatar_template last_poster: type: object additionalProperties: false properties: id: type: integer username: type: string name: type: string avatar_template: type: string required: - id - username - name - avatar_template required: - can_edit - notification_level - can_move_posts - can_delete - can_remove_allowed_users - can_create_post - can_reply_as_new_topic - can_convert_topic - can_review_topic - can_close_topic - can_archive_topic - can_split_merge_topic - can_edit_staff_notes - can_toggle_topic_visibility - can_pin_unpin_topic - can_moderate_category - can_remove_self_id - created_by - last_poster required: - post_stream - timeline_lookup - suggested_topics - tags - tags_descriptions - id - title - fancy_title - posts_count - created_at - views - reply_count - like_count - last_posted_at - visible - closed - archived - has_summary - archetype - slug - category_id - word_count - deleted_at - user_id - featured_link - pinned_globally - pinned_at - pinned_until - image_url - slow_mode_seconds - draft - draft_key - draft_sequence - unpinned - pinned - highest_post_number - deleted_by - has_deleted - actions_summary - chunk_size - bookmarked - bookmarks - topic_timer - message_bus_last_id - participant_count - show_read_indicator - thumbnails - slow_mode_enabled_until - details delete: summary: Remove a topic tags: - Topics operationId: removeTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: specific posts /t/-/{id}.json: put: summary: Update a topic tags: - Topics operationId: updateTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated content: application/json: schema: type: object properties: basic_topic: type: object properties: id: type: integer title: type: string fancy_title: type: string slug: type: string posts_count: type: integer requestBody: content: application/json: schema: type: object properties: topic: type: object properties: title: type: string category_id: type: integer /t/{id}/invite.json: post: summary: Invite to topic tags: - Topics operationId: inviteToTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated content: application/json: schema: type: object properties: user: type: object properties: id: type: integer username: type: string name: type: string avatar_template: type: string requestBody: content: application/json: schema: type: object properties: user: type: string email: type: string /t/{id}/invite-group.json: post: summary: Invite group to topic tags: - Topics operationId: inviteGroupToTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: invites to a PM content: application/json: schema: type: object properties: group: type: object properties: id: type: integer name: type: string requestBody: content: application/json: schema: type: object properties: group: type: string description: The name of the group to invite should_notify: type: boolean description: Whether to notify the group, it defaults to true /t/{id}/bookmark.json: put: summary: Bookmark topic tags: - Topics operationId: bookmarkTopic parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated /t/{id}/status.json: put: summary: Update the status of a topic tags: - Topics operationId: updateTopicStatus parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated content: application/json: schema: type: object properties: success: type: string example: OK topic_status_update: type: - string - 'null' requestBody: content: application/json: schema: type: object properties: status: type: string enum: - closed - pinned - pinned_globally - archived - visible enabled: type: string enum: - 'true' - 'false' until: type: string description: Only required for `pinned` and `pinned_globally` example: '2030-12-31' required: - status - enabled /latest.json: get: summary: Get the latest topics tags: - Topics operationId: listLatestTopics parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: order in: query description: 'Enum: `default`, `created`, `activity`, `views`, `posts`, `category`, `likes`, `op_likes`, `posters`' schema: type: string - name: ascending in: query description: Defaults to `desc`, add `ascending=true` to sort asc schema: type: string - name: per_page in: query description: Maximum number of topics returned, between 1-100 schema: type: integer responses: '200': description: topic updated content: application/json: schema: type: object properties: users: type: array items: type: object properties: id: type: integer username: type: string name: type: - string - 'null' avatar_template: type: string primary_groups: type: array items: {} topic_list: type: object properties: can_create_topic: type: boolean draft: type: - string - 'null' draft_key: type: string draft_sequence: type: integer per_page: type: integer topics: type: array items: type: object properties: id: type: integer title: type: string fancy_title: type: string slug: type: string posts_count: type: integer reply_count: type: integer highest_post_number: type: integer image_url: type: string created_at: type: string last_posted_at: type: string bumped: type: boolean bumped_at: type: string archetype: type: string unseen: type: boolean last_read_post_number: type: integer unread_posts: type: integer pinned: type: boolean unpinned: type: - string - 'null' visible: type: boolean closed: type: boolean archived: type: boolean notification_level: type: integer bookmarked: type: boolean liked: type: boolean views: type: integer like_count: type: integer has_summary: type: boolean last_poster_username: type: string category_id: type: integer op_like_count: type: integer pinned_globally: type: boolean featured_link: type: - string - 'null' posters: type: array items: type: object properties: extras: type: string description: type: string user_id: type: integer primary_group_id: type: - integer - 'null' /top.json: get: summary: Get the top topics filtered by period tags: - Topics operationId: listTopTopics parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: period in: query description: 'Enum: `all`, `yearly`, `quarterly`, `monthly`, `weekly`, `daily`' schema: type: string - name: per_page in: query description: Maximum number of topics returned, between 1-100 schema: type: integer responses: '200': description: response content: application/json: schema: type: object properties: users: type: array items: type: object properties: id: type: integer username: type: string name: type: string avatar_template: type: string primary_groups: type: array items: {} topic_list: type: object properties: can_create_topic: type: boolean draft: type: - string - 'null' draft_key: type: string draft_sequence: type: integer for_period: type: string per_page: type: integer topics: type: array items: type: object properties: id: type: integer title: type: string fancy_title: type: string slug: type: string posts_count: type: integer reply_count: type: integer highest_post_number: type: integer image_url: type: - string - 'null' created_at: type: string last_posted_at: type: string bumped: type: boolean bumped_at: type: string archetype: type: string unseen: type: boolean last_read_post_number: type: integer unread_posts: type: integer pinned: type: boolean unpinned: type: boolean visible: type: boolean closed: type: boolean archived: type: boolean notification_level: type: integer bookmarked: type: boolean liked: type: boolean views: type: integer like_count: type: integer has_summary: type: boolean last_poster_username: type: string category_id: type: integer op_like_count: type: integer pinned_globally: type: boolean featured_link: type: - string - 'null' posters: type: array items: type: object properties: extras: type: - string - 'null' description: type: string user_id: type: integer primary_group_id: type: - integer - 'null' /t/{id}/notifications.json: post: summary: Set notification level tags: - Topics operationId: setNotificationLevel parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated content: application/json: schema: type: object properties: success: type: string example: OK requestBody: content: application/json: schema: type: object properties: notification_level: type: string enum: - '0' - '1' - '2' - '3' required: - notification_level /t/{id}/change-timestamp.json: put: summary: Update topic timestamp tags: - Topics operationId: updateTopicTimestamp parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated content: application/json: schema: type: object properties: success: type: string example: OK requestBody: content: application/json: schema: type: object properties: timestamp: type: string example: '1594291380' required: - timestamp /t/{id}/timer.json: post: summary: Create topic timer tags: - Topics operationId: createTopicTimer parameters: - name: Api-Key in: header required: true schema: type: string - name: Api-Username in: header required: true schema: type: string - name: id in: path schema: type: string required: true responses: '200': description: topic updated content: application/json: schema: type: object properties: success: type: string example: OK execute_at: type: string duration: type: - string - 'null' based_on_last_post: type: boolean closed: type: boolean category_id: type: - integer - 'null' requestBody: content: application/json: schema: type: object properties: time: type: string example: '' status_type: type: string based_on_last_post: type: boolean category_id: type: integer /t/external_id/{external_id}.json: get: summary: Get topic by external_id tags: - Topics operationId: getTopicByExternalId parameters: - name: external_id in: path required: true schema: type: string responses: '301': description: redirects to /t/{topic_id}.json