# Discourse

> Run a Discourse community forum from a workflow. Create and organise categories, start topics and reply to them, edit and delete posts, close or pin topics, send personal messages, search the forum, and look up members.

App · Publishing & Community · 20 actions. Web page: https://docs.lodol.com/docs/integrations/discourse

## Actions

### Create category

Create a category, optionally as a subcategory of another. The name must be unique among its siblings. Needs an admin API username. Discourse also creates the category's 'About' topic, which does not count towards its topic count.

**Inputs**

- Name (`name`, text, required): The category's name, unique among its siblings.
- Colour (`color`, text): The category's colour as six hex digits, with or without a leading #, such as 0088CC.
- Text colour (`text_color`, text): The colour of the category's name on its badge, as six hex digits. Usually FFFFFF on a dark colour.
- Parent category (`parent_category_id`, text): Make this a subcategory of the chosen category. Leave empty for a top-level category.
- Slug (`slug`, text): The part of the category's URL after /c/. Leave empty and Discourse derives one from the name.

**Outputs**

- `all_topics_wiki` (true/false)
- `allow_badges` (true/false)
- `allow_global_tags` (true/false)
- `allowed_tag_groups` (list)
- `allowed_tags` (list)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `color` (text)
- `custom_fields` (object)
- `default_list_filter` (text)
- `default_top_period` (text)
- `default_view` (text)
- `description` (text)
- `description_excerpt` (text)
- `description_text` (text)
- `email_in` (text)
- `email_in_allow_strangers` (true/false)
- `emoji` (text)
- `has_children` (true/false)
- `icon` (text)
- `id` (number)
- `locale` (text)
- `mailinglist_mirror` (true/false)
- `minimum_required_tags` (number)
- `name` (text)
- `notification_level` (number)
- `num_featured_topics` (number)
- `parent_category_id` (number)
- `permission` (number)
- `position` (number)
- `post_count` (number)
- `read_restricted` (true/false)
- `search_priority` (number)
- `show_subcategory_list` (true/false)
- `slug` (text)
- `sort_order` (text)
- `style_type` (text)
- `subcategory_count` (number)
- `subcategory_list_style` (text)
- `text_color` (text)
- `topic_count` (number)
- `topic_featured_link_allowed` (true/false)
- `topic_template` (text)
- `topic_url` (text)
- `uploaded_background` (object)
- `uploaded_logo` (object)

**Example output**

```json
{
  "can_delete": false,
  "can_edit": true,
  "color": "0088CC",
  "description": "News from the team.",
  "description_text": "News from the team.",
  "has_children": false,
  "id": 5,
  "name": "Announcements",
  "notification_level": 1,
  "parent_category_id": null,
  "permission": 1,
  "position": 1,
  "post_count": 87,
  "read_restricted": false,
  "slug": "announcements",
  "subcategory_count": 0,
  "text_color": "FFFFFF",
  "topic_count": 12,
  "topic_url": "/t/about-the-announcements-category/9"
}
```

### Create post

Reply in an existing topic with a Markdown body. Give a post number to reply to one post in particular rather than to the topic as a whole.

**Inputs**

- Topic (`topic_id`, text, required): The topic to act on: its ID, or its URL on the forum such as https://forum.example.com/t/welcome/8.
- Body (`raw`, text, required): The post body, in Markdown. Discourse enforces a minimum length (20 characters by default).
- Reply to post number (`reply_to_post_number`, number): The number of the post within the topic to reply to (1 is the first post). Leave empty to reply to the topic. From 1 to 1000000.

**Outputs**

- `actions_summary` (list)
- `admin` (true/false)
- `avatar_template` (text)
- `bookmarked` (true/false)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `can_recover` (true/false)
- `can_wiki` (true/false)
- `category_id` (number)
- `cooked` (text)
- `created_at` (text)
- `deleted_at` (text)
- `display_username` (text)
- `edit_reason` (text)
- `excerpt` (text)
- `hidden` (true/false)
- `id` (number)
- `incoming_link_count` (number)
- `moderator` (true/false)
- `name` (text)
- `post_number` (number)
- `post_type` (number)
- `post_url` (text)
- `posts_count` (number)
- `primary_group_name` (text)
- `quote_count` (number)
- `raw` (text)
- `readers_count` (number)
- `reads` (number)
- `reply_count` (number)
- `reply_to_post_number` (number)
- `score` (number)
- `staff` (true/false)
- `topic_html_title` (text)
- `topic_id` (number)
- `topic_slug` (text)
- `topic_title` (text)
- `truncated` (true/false)
- `trust_level` (number)
- `updated_at` (text)
- `user_deleted` (true/false)
- `user_id` (number)
- `user_title` (text)
- `username` (text)
- `version` (number)
- `wiki` (true/false)
- `yours` (true/false)

**Example output**

```json
{
  "admin": true,
  "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
  "can_delete": true,
  "can_edit": true,
  "category_id": 5,
  "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
  "created_at": "2026-08-30T09:12:44.000Z",
  "deleted_at": null,
  "display_username": "Ada Lovelace",
  "edit_reason": null,
  "hidden": false,
  "id": 731,
  "moderator": false,
  "name": "Ada Lovelace",
  "post_number": 1,
  "post_type": 1,
  "post_url": "/t/release-3-5-is-out/42/1",
  "posts_count": 4,
  "raw": "The 3.5 release ships today with **faster search**.",
  "readers_count": 39,
  "reads": 40,
  "reply_count": 3,
  "reply_to_post_number": null,
  "score": 82.4,
  "staff": true,
  "topic_id": 42,
  "topic_slug": "release-3-5-is-out",
  "topic_title": "Release 3.5 is out",
  "trust_level": 4,
  "updated_at": "2026-08-30T09:12:44.000Z",
  "user_id": 3,
  "username": "ada",
  "version": 1,
  "wiki": false,
  "yours": true
}
```

### Create topic

Start a new topic with a title and a Markdown body, in a category or in the forum's default one. Returns the topic's first post; its 'topic_id' is the new topic. Give an external ID or an embed URL to link the topic to a record in another system.

**Inputs**

- Title (`title`, text, required): The title. Discourse enforces a minimum length (15 characters by default) and refuses a title identical to an existing topic's.
- Body (`raw`, text, required): The post body, in Markdown. Discourse enforces a minimum length (20 characters by default).
- Category (`category_id`, text): Where to post it. Leave empty for the forum's default category, if the forum allows uncategorised topics.
- Backdate to (`created_at`, date and time): Give the topic this creation time instead of now, for imported content. Leave empty normally.
- External ID (`external_id`, text): An ID from another system to associate with the topic, so it can be found again by that ID.
- Embed URL (`embed_url`, text): A page URL to associate with the topic, for using the forum as a comment thread for that page.

**Outputs**

- `actions_summary` (list)
- `admin` (true/false)
- `avatar_template` (text)
- `bookmarked` (true/false)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `can_recover` (true/false)
- `can_wiki` (true/false)
- `category_id` (number)
- `cooked` (text)
- `created_at` (text)
- `deleted_at` (text)
- `display_username` (text)
- `edit_reason` (text)
- `excerpt` (text)
- `hidden` (true/false)
- `id` (number)
- `incoming_link_count` (number)
- `moderator` (true/false)
- `name` (text)
- `post_number` (number)
- `post_type` (number)
- `post_url` (text)
- `posts_count` (number)
- `primary_group_name` (text)
- `quote_count` (number)
- `raw` (text)
- `readers_count` (number)
- `reads` (number)
- `reply_count` (number)
- `reply_to_post_number` (number)
- `score` (number)
- `staff` (true/false)
- `topic_html_title` (text)
- `topic_id` (number)
- `topic_slug` (text)
- `topic_title` (text)
- `truncated` (true/false)
- `trust_level` (number)
- `updated_at` (text)
- `user_deleted` (true/false)
- `user_id` (number)
- `user_title` (text)
- `username` (text)
- `version` (number)
- `wiki` (true/false)
- `yours` (true/false)

**Example output**

```json
{
  "admin": true,
  "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
  "can_delete": true,
  "can_edit": true,
  "category_id": 5,
  "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
  "created_at": "2026-08-30T09:12:44.000Z",
  "deleted_at": null,
  "display_username": "Ada Lovelace",
  "edit_reason": null,
  "hidden": false,
  "id": 731,
  "moderator": false,
  "name": "Ada Lovelace",
  "post_number": 1,
  "post_type": 1,
  "post_url": "/t/release-3-5-is-out/42/1",
  "posts_count": 4,
  "raw": "The 3.5 release ships today with **faster search**.",
  "readers_count": 39,
  "reads": 40,
  "reply_count": 3,
  "reply_to_post_number": null,
  "score": 82.4,
  "staff": true,
  "topic_id": 42,
  "topic_slug": "release-3-5-is-out",
  "topic_title": "Release 3.5 is out",
  "trust_level": 4,
  "updated_at": "2026-08-30T09:12:44.000Z",
  "user_id": 3,
  "username": "ada",
  "version": 1,
  "wiki": false,
  "yours": true
}
```

### Delete category

Delete a category. Discourse only allows this for a category with no topics and no subcategories - delete or move its topics first. Needs an admin API username.

**Inputs**

- Category (`category_id`, text, required): The category to act on. Pick one, or paste a category ID or its URL on the forum.

**Outputs**

- `deleted` (true/false)
- `id` (number)
- `resource` (text)

**Example output**

```json
{
  "deleted": true,
  "id": 5,
  "resource": "category"
}
```

### Delete post

Delete a post. Deleting a topic's first post deletes the whole topic. Staff can recover it for a while afterwards. Deleting another member's post needs a staff API username.

**Inputs**

- Post ID (`post_id`, text, required): The post to act on, as the 'id' a create, get-topic or list step returned. This is the post's own ID, not its number within the topic.

**Outputs**

- `deleted` (true/false)
- `id` (number)
- `resource` (text)

**Example output**

```json
{
  "deleted": true,
  "id": 731,
  "resource": "post"
}
```

### Delete topic

Delete a topic and every post in it. Staff can recover it from the forum for a while afterwards; members cannot. The API username needs to be staff, or the topic's own author.

**Inputs**

- Topic (`topic_id`, text, required): The topic to act on: its ID, or its URL on the forum such as https://forum.example.com/t/welcome/8.

**Outputs**

- `deleted` (true/false)
- `id` (number)
- `resource` (text)

**Example output**

```json
{
  "deleted": true,
  "id": 42,
  "resource": "topic"
}
```

### Get category

Read one category in full: its name, slug, colours, description, topic and post counts, parent, permissions and settings.

**Inputs**

- Category (`category_id`, text, required): The category to act on. Pick one, or paste a category ID or its URL on the forum.

**Outputs**

- `all_topics_wiki` (true/false)
- `allow_badges` (true/false)
- `allow_global_tags` (true/false)
- `allowed_tag_groups` (list)
- `allowed_tags` (list)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `color` (text)
- `custom_fields` (object)
- `default_list_filter` (text)
- `default_top_period` (text)
- `default_view` (text)
- `description` (text)
- `description_excerpt` (text)
- `description_text` (text)
- `email_in` (text)
- `email_in_allow_strangers` (true/false)
- `emoji` (text)
- `has_children` (true/false)
- `icon` (text)
- `id` (number)
- `locale` (text)
- `mailinglist_mirror` (true/false)
- `minimum_required_tags` (number)
- `name` (text)
- `notification_level` (number)
- `num_featured_topics` (number)
- `parent_category_id` (number)
- `permission` (number)
- `position` (number)
- `post_count` (number)
- `read_restricted` (true/false)
- `search_priority` (number)
- `show_subcategory_list` (true/false)
- `slug` (text)
- `sort_order` (text)
- `style_type` (text)
- `subcategory_count` (number)
- `subcategory_list_style` (text)
- `text_color` (text)
- `topic_count` (number)
- `topic_featured_link_allowed` (true/false)
- `topic_template` (text)
- `topic_url` (text)
- `uploaded_background` (object)
- `uploaded_logo` (object)

**Example output**

```json
{
  "can_delete": false,
  "can_edit": true,
  "color": "0088CC",
  "description": "News from the team.",
  "description_text": "News from the team.",
  "has_children": false,
  "id": 5,
  "name": "Announcements",
  "notification_level": 1,
  "parent_category_id": null,
  "permission": 1,
  "position": 1,
  "post_count": 87,
  "read_restricted": false,
  "slug": "announcements",
  "subcategory_count": 0,
  "text_color": "FFFFFF",
  "topic_count": 12,
  "topic_url": "/t/about-the-announcements-category/9"
}
```

### Get post

Read one post: its Markdown source and rendered HTML, author, topic, position in the topic, like and read counts, and whether it has been edited or hidden.

**Inputs**

- Post ID (`post_id`, text, required): The post to act on, as the 'id' a create, get-topic or list step returned. This is the post's own ID, not its number within the topic.

**Outputs**

- `actions_summary` (list)
- `admin` (true/false)
- `avatar_template` (text)
- `bookmarked` (true/false)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `can_recover` (true/false)
- `can_wiki` (true/false)
- `category_id` (number)
- `cooked` (text)
- `created_at` (text)
- `deleted_at` (text)
- `display_username` (text)
- `edit_reason` (text)
- `excerpt` (text)
- `hidden` (true/false)
- `id` (number)
- `incoming_link_count` (number)
- `moderator` (true/false)
- `name` (text)
- `post_number` (number)
- `post_type` (number)
- `post_url` (text)
- `posts_count` (number)
- `primary_group_name` (text)
- `quote_count` (number)
- `raw` (text)
- `readers_count` (number)
- `reads` (number)
- `reply_count` (number)
- `reply_to_post_number` (number)
- `score` (number)
- `staff` (true/false)
- `topic_html_title` (text)
- `topic_id` (number)
- `topic_slug` (text)
- `topic_title` (text)
- `truncated` (true/false)
- `trust_level` (number)
- `updated_at` (text)
- `user_deleted` (true/false)
- `user_id` (number)
- `user_title` (text)
- `username` (text)
- `version` (number)
- `wiki` (true/false)
- `yours` (true/false)

**Example output**

```json
{
  "admin": true,
  "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
  "can_delete": true,
  "can_edit": true,
  "category_id": 5,
  "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
  "created_at": "2026-08-30T09:12:44.000Z",
  "deleted_at": null,
  "display_username": "Ada Lovelace",
  "edit_reason": null,
  "hidden": false,
  "id": 731,
  "moderator": false,
  "name": "Ada Lovelace",
  "post_number": 1,
  "post_type": 1,
  "post_url": "/t/release-3-5-is-out/42/1",
  "posts_count": 4,
  "raw": "The 3.5 release ships today with **faster search**.",
  "readers_count": 39,
  "reads": 40,
  "reply_count": 3,
  "reply_to_post_number": null,
  "score": 82.4,
  "staff": true,
  "topic_id": 42,
  "topic_slug": "release-3-5-is-out",
  "topic_title": "Release 3.5 is out",
  "trust_level": 4,
  "updated_at": "2026-08-30T09:12:44.000Z",
  "user_id": 3,
  "username": "ada",
  "version": 1,
  "wiki": false,
  "yours": true
}
```

### Get topic

Read one topic in full, with its first page of posts under 'post_stream.posts' - each post's Markdown source, rendered HTML, author and like count - plus the topic's category, tags, status flags and who created it.

**Inputs**

- Topic (`topic_id`, text, required): The topic to act on: its ID, or its URL on the forum such as https://forum.example.com/t/welcome/8.

**Outputs**

- `archetype` (text)
- `archived` (true/false)
- `category_id` (number)
- `closed` (true/false)
- `created_at` (text)
- `deleted_at` (text)
- `details` (object)
- `fancy_title` (text)
- `featured_link` (text)
- `has_summary` (true/false)
- `highest_post_number` (number)
- `id` (number)
- `last_posted_at` (text)
- `like_count` (number)
- `participant_count` (number)
- `pinned` (true/false)
- `pinned_at` (text)
- `pinned_globally` (true/false)
- `pinned_until` (text)
- `post_stream` (object)
- `posts_count` (number)
- `reply_count` (number)
- `slug` (text)
- `suggested_topics` (list)
- `tags` (list)
- `title` (text)
- `user_id` (number)
- `views` (number)
- `visible` (true/false)
- `word_count` (number)

**Example output**

```json
{
  "archetype": "regular",
  "archived": false,
  "category_id": 5,
  "closed": false,
  "created_at": "2026-08-30T09:12:44.000Z",
  "deleted_at": null,
  "details": {
    "can_delete": true,
    "can_edit": true,
    "can_reply_as_new_topic": true,
    "created_by": {
      "id": 3,
      "name": "Ada Lovelace",
      "username": "ada"
    },
    "last_poster": {
      "id": 3,
      "name": "Ada Lovelace",
      "username": "ada"
    }
  },
  "fancy_title": "Release 3.5 is out",
  "featured_link": null,
  "has_summary": false,
  "highest_post_number": 4,
  "id": 42,
  "last_posted_at": "2026-09-01T16:41:08.000Z",
  "like_count": 9,
  "participant_count": 3,
  "pinned": false,
  "pinned_at": null,
  "pinned_globally": false,
  "pinned_until": null,
  "post_stream": {
    "posts": [
      {
        "admin": true,
        "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
        "can_delete": true,
        "can_edit": true,
        "category_id": 5,
        "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
        "created_at": "2026-08-30T09:12:44.000Z",
        "deleted_at": null,
        "display_username": "Ada Lovelace",
        "edit_reason": null,
        "hidden": false,
        "id": 731,
        "moderator": false,
        "name": "Ada Lovelace",
        "post_number": 1,
        "post_type": 1,
        "post_url": "/t/release-3-5-is-out/42/1",
        "posts_count": 4,
        "raw": "The 3.5 release ships today with **faster search**.",
        "readers_count": 39,
        "reads": 40,
        "reply_count": 3,
        "reply_to_post_number": null,
        "score": 82.4,
        "staff": true,
        "topic_id": 42,
        "topic_slug": "release-3-5-is-out",
        "topic_title": "Release 3.5 is out",
        "trust_level": 4,
        "updated_at": "2026-08-30T09:12:44.000Z",
        "user_id": 3,
        "username": "ada",
        "version": 1,
        "wiki": false,
        "yours": true
      }
    ],
    "stream": [
      731,
      732,
      733,
      734
    ]
  },
  "posts_count": 4,
  "reply_count": 3,
  "slug": "release-3-5-is-out",
  "suggested_topics": [],
  "tags": [
    "release"
  ],
  "title": "Release 3.5 is out",
  "user_id": 3,
  "views": 214,
  "visible": true,
  "word_count": 118
}
```

### Get user

Read a member's profile: name, title, trust level, whether they are staff, post and topic counts, when they joined and were last seen, bio, groups, and their custom profile fields.

**Inputs**

- Username (`username`, text, required): The member's username, with or without a leading @, or their profile URL.

**Outputs**

- `admin` (true/false)
- `avatar_template` (text)
- `badge_count` (number)
- `bio_cooked` (text)
- `bio_excerpt` (text)
- `bio_raw` (text)
- `can_be_deleted` (true/false)
- `can_delete_all_posts` (true/false)
- `can_edit` (true/false)
- `can_send_private_message_to_user` (true/false)
- `can_send_private_messages` (true/false)
- `created_at` (text)
- `custom_fields` (object)
- `email` (text)
- `flair_name` (text)
- `flair_url` (text)
- `groups` (list)
- `has_title_badges` (true/false)
- `id` (number)
- `ignored` (true/false)
- `last_posted_at` (text)
- `last_seen_at` (text)
- `locale` (text)
- `location` (text)
- `moderator` (true/false)
- `muted` (true/false)
- `name` (text)
- `pending_count` (number)
- `post_count` (number)
- `primary_group_id` (number)
- `primary_group_name` (text)
- `profile_view_count` (number)
- `recent_time_read` (number)
- `second_factor_enabled` (true/false)
- `staged` (true/false)
- `time_read` (number)
- `title` (text)
- `topic_count` (number)
- `trust_level` (number)
- `uploaded_avatar_id` (number)
- `user_fields` (object)
- `username` (text)
- `website` (text)
- `website_name` (text)

**Example output**

```json
{
  "admin": true,
  "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
  "badge_count": 12,
  "bio_excerpt": "Building the forum.",
  "can_be_deleted": false,
  "created_at": "2025-03-14T10:00:00.000Z",
  "groups": [
    {
      "display_name": "admins",
      "id": 1,
      "name": "admins"
    }
  ],
  "id": 3,
  "last_posted_at": "2026-09-01T16:41:08.000Z",
  "last_seen_at": "2026-09-08T08:02:11.000Z",
  "moderator": false,
  "name": "Ada Lovelace",
  "post_count": 340,
  "staged": false,
  "time_read": 45120,
  "title": "Founder",
  "topic_count": 28,
  "trust_level": 4,
  "username": "ada"
}
```

### List categories

List the forum's categories with each one's ID, name, slug, colours, topic and post counts, and parent. Tick 'Include subcategories' to get every subcategory too, flattened into the same list.

**Inputs**

- Include subcategories (`include_subcategories`, true/false): Include every subcategory in the list.

**Outputs**: The forum's categories

- `count` (number): How many were returned
- `items` (list)

**Example output**

```json
{
  "count": 1,
  "items": [
    {
      "can_delete": false,
      "can_edit": true,
      "color": "0088CC",
      "description": "News from the team.",
      "description_text": "News from the team.",
      "has_children": false,
      "id": 5,
      "name": "Announcements",
      "notification_level": 1,
      "parent_category_id": null,
      "permission": 1,
      "position": 1,
      "post_count": 87,
      "read_restricted": false,
      "slug": "announcements",
      "subcategory_count": 0,
      "text_color": "FFFFFF",
      "topic_count": 12,
      "topic_url": "/t/about-the-announcements-category/9"
    }
  ]
}
```

### List latest posts

The newest posts across the whole forum, newest first, with each post's author, topic title, category and Markdown source. To read older ones, pass 'next_before' back as 'Before post ID'. Poll it to react to new posts.

**Inputs**

- Before post ID (`before`, number): Only posts with an ID lower than this - the 'next_before' a previous page returned.

**Outputs**: The newest posts across the forum, newest first

- `count` (number): Posts returned
- `items` (list)
- `next_before` (number): Pass this as 'before' to read the posts older than these, or empty when there are none

**Example output**

```json
{
  "count": 1,
  "items": [
    {
      "admin": true,
      "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
      "can_delete": true,
      "can_edit": true,
      "category_id": 5,
      "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
      "created_at": "2026-08-30T09:12:44.000Z",
      "deleted_at": null,
      "display_username": "Ada Lovelace",
      "edit_reason": null,
      "hidden": false,
      "id": 731,
      "moderator": false,
      "name": "Ada Lovelace",
      "post_number": 1,
      "post_type": 1,
      "post_url": "/t/release-3-5-is-out/42/1",
      "posts_count": 4,
      "raw": "The 3.5 release ships today with **faster search**.",
      "readers_count": 39,
      "reads": 40,
      "reply_count": 3,
      "reply_to_post_number": null,
      "score": 82.4,
      "staff": true,
      "topic_id": 42,
      "topic_slug": "release-3-5-is-out",
      "topic_title": "Release 3.5 is out",
      "trust_level": 4,
      "updated_at": "2026-08-30T09:12:44.000Z",
      "user_id": 3,
      "username": "ada",
      "version": 1,
      "wiki": false,
      "yours": true
    }
  ],
  "next_before": 731
}
```

### List topics

List the forum's topics, most recently bumped first, or one category's. Each one reports its title, ID, slug, category, tags, post and view counts, whether it is closed or pinned, and when it was last posted in. Pick an order to sort by creation date, activity, views, posts or likes instead.

**Inputs**

- Category (`category_id`, text): Limit this to one category. Pick one, or paste a category ID or its URL. Leave empty for the whole forum.
- Order (`order`, text): What to sort by. Defaults to most recently bumped. One of: `default` (Default (bumped most recently)), `created`, `activity` (Latest activity), `views`, `posts` (Post count), `likes`, `op_likes` (Likes on the first post), `posters` (Number of posters), `category`.
- Oldest or smallest first (`ascending`, true/false): Reverse the order. Discourse lists newest or largest first by default.
- Page (`page`, number): Which page to read. Discourse counts topic pages from 0. From 0 to 1000000. Default: `0`.
- Results per page (`per_page`, number): How many to return, 1-100. Defaults to 30. From 1 to 100. Default: `30`.

**Outputs**: The topics, in the order asked for

- `count` (number): Records on this page
- `has_more` (true/false): Whether the forum has another page
- `items` (list)
- `next_page` (number): The page to ask for next, or empty at the end
- `page` (number): The page that was read
- `per_page` (number): The page size used

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "items": [
    {
      "archetype": "regular",
      "archived": false,
      "bumped": true,
      "bumped_at": "2026-09-01T16:41:08.000Z",
      "category_id": 5,
      "closed": false,
      "created_at": "2026-08-30T09:12:44.000Z",
      "excerpt": "The 3.5 release ships today with...",
      "fancy_title": "Release 3.5 is out",
      "highest_post_number": 4,
      "id": 42,
      "last_posted_at": "2026-09-01T16:41:08.000Z",
      "last_poster_username": "ada",
      "like_count": 9,
      "pinned": false,
      "posters": [
        {
          "description": "Original Poster",
          "extras": "latest",
          "user_id": 3
        }
      ],
      "posts_count": 4,
      "reply_count": 3,
      "slug": "release-3-5-is-out",
      "tags": [
        "release"
      ],
      "title": "Release 3.5 is out",
      "views": 214,
      "visible": true
    }
  ],
  "next_page": null,
  "page": 0,
  "per_page": 30
}
```

### List users

List the forum's members from the admin panel: active, new, staff, suspended or silenced. Each one reports their username, name, trust level, join date, last visit and activity counts. Filter by email to find one member. 100 a page. Needs an admin API username.

**Inputs**

- Which members (`flag`, text): Which member list to read. Defaults to active members. One of: `active` (Active members), `new` (New members), `staff`, `suspended`, `blocked` (Silenced), `suspect` (Suspect accounts). Default: `active`.
- Order (`order`, text): What to sort by. Defaults to Discourse's own order. One of: `created` (Joined), `seen` (Last seen), `username`, `email`, `trust_level` (Trust level), `days_visited` (Days visited), `posts`, `posts_read` (Posts read), `topics_viewed` (Topics viewed), `read_time` (Time read), `last_emailed` (Last emailed).
- Oldest or smallest first (`ascending`, true/false): Reverse the order. Discourse lists newest or largest first by default.
- Email (`email`, text): Only the member with this email address.
- Include email addresses (`show_emails`, true/false): Fill in each member's email. Discourse records this in the staff action log.
- Page (`page`, number): Which page to read. Defaults to the first. From 1 to 1000000. Default: `1`.

**Outputs**: The members on this page

- `count` (number): Members on this page
- `has_more` (true/false): Whether the page was full, so another may exist
- `items` (list)
- `next_page` (number)
- `page` (number): The page that was read

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "items": [
    {
      "active": true,
      "admin": true,
      "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
      "created_at": "2025-03-14T10:00:00.000Z",
      "days_visited": 402,
      "id": 3,
      "last_emailed_at": "2026-09-07T06:00:00.000Z",
      "last_seen_at": "2026-09-08T08:02:11.000Z",
      "moderator": false,
      "name": "Ada Lovelace",
      "post_count": 340,
      "posts_read_count": 5120,
      "staged": false,
      "time_read": 45120,
      "title": "Founder",
      "topics_entered": 890,
      "trust_level": 4,
      "username": "ada"
    }
  ],
  "next_page": null,
  "page": 1
}
```

### Search

Search the forum's posts, topics, members, categories and tags. The query takes Discourse's search language: 'in:title', '#category-slug', '@username', 'tags:name', 'after:2026-01-01', 'status:open'. Results come back grouped by kind, with the matched text of each post in 'blurb'.

**Inputs**

- Query (`query`, text, required): What to search for, with any of Discourse's search qualifiers.
- Order (`order`, text): How to order the results. Defaults to relevance. One of: `relevance`, `latest` (Latest post), `latest_topic` (Latest topic), `likes` (Most liked), `views` (Most viewed).
- Page (`page`, number): Which page to read. Defaults to the first. From 1 to 1000000. Default: `1`.

**Outputs**: Everything the forum matched, grouped by kind

- `categories` (list)
- `category_count` (number)
- `has_more` (true/false): Whether another page exists
- `next_page` (number)
- `page` (number)
- `post_count` (number)
- `posts` (list)
- `tag_count` (number)
- `tags` (list)
- `term` (text): The query as searched
- `topic_count` (number)
- `topics` (list)
- `user_count` (number)
- `users` (list)

**Example output**

```json
{
  "categories": [],
  "category_count": 0,
  "has_more": false,
  "next_page": null,
  "page": 1,
  "post_count": 1,
  "posts": [
    {
      "blurb": "The 3.5 release ships today with faster search.",
      "created_at": "2026-08-30T09:12:44.000Z",
      "id": 731,
      "like_count": 9,
      "post_number": 1,
      "topic_id": 42,
      "username": "ada"
    }
  ],
  "tag_count": 0,
  "tags": [],
  "term": "faster search",
  "topic_count": 1,
  "topics": [
    {
      "archetype": "regular",
      "archived": false,
      "bumped": true,
      "bumped_at": "2026-09-01T16:41:08.000Z",
      "category_id": 5,
      "closed": false,
      "created_at": "2026-08-30T09:12:44.000Z",
      "excerpt": "The 3.5 release ships today with...",
      "fancy_title": "Release 3.5 is out",
      "highest_post_number": 4,
      "id": 42,
      "last_posted_at": "2026-09-01T16:41:08.000Z",
      "last_poster_username": "ada",
      "like_count": 9,
      "pinned": false,
      "posters": [
        {
          "description": "Original Poster",
          "extras": "latest",
          "user_id": 3
        }
      ],
      "posts_count": 4,
      "reply_count": 3,
      "slug": "release-3-5-is-out",
      "tags": [
        "release"
      ],
      "title": "Release 3.5 is out",
      "views": 214,
      "visible": true
    }
  ],
  "user_count": 0,
  "users": []
}
```

### Send personal message

Send a personal message from the API username to one or more members. Leave the recipients empty to send it to the API username itself, as a note. Returns the message's first post; its 'topic_id' is the message thread, which 'Get topic' and 'Create post' can read and reply to.

**Inputs**

- Recipients (`target_recipients`, text): Usernames to send it to, separated by commas. Leave empty to message the API username itself.
- Title (`title`, text, required): The title. Discourse enforces a minimum length (15 characters by default) and refuses a title identical to an existing topic's.
- Body (`raw`, text, required): The post body, in Markdown. Discourse enforces a minimum length (20 characters by default).

**Outputs**

- `actions_summary` (list)
- `admin` (true/false)
- `avatar_template` (text)
- `bookmarked` (true/false)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `can_recover` (true/false)
- `can_wiki` (true/false)
- `category_id` (number)
- `cooked` (text)
- `created_at` (text)
- `deleted_at` (text)
- `display_username` (text)
- `edit_reason` (text)
- `excerpt` (text)
- `hidden` (true/false)
- `id` (number)
- `incoming_link_count` (number)
- `moderator` (true/false)
- `name` (text)
- `post_number` (number)
- `post_type` (number)
- `post_url` (text)
- `posts_count` (number)
- `primary_group_name` (text)
- `quote_count` (number)
- `raw` (text)
- `readers_count` (number)
- `reads` (number)
- `reply_count` (number)
- `reply_to_post_number` (number)
- `score` (number)
- `staff` (true/false)
- `topic_html_title` (text)
- `topic_id` (number)
- `topic_slug` (text)
- `topic_title` (text)
- `truncated` (true/false)
- `trust_level` (number)
- `updated_at` (text)
- `user_deleted` (true/false)
- `user_id` (number)
- `user_title` (text)
- `username` (text)
- `version` (number)
- `wiki` (true/false)
- `yours` (true/false)

**Example output**

```json
{
  "admin": true,
  "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
  "can_delete": true,
  "can_edit": true,
  "category_id": 5,
  "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
  "created_at": "2026-08-30T09:12:44.000Z",
  "deleted_at": null,
  "display_username": "Ada Lovelace",
  "edit_reason": null,
  "hidden": false,
  "id": 731,
  "moderator": false,
  "name": "Ada Lovelace",
  "post_number": 1,
  "post_type": 1,
  "post_url": "/t/release-3-5-is-out/42/1",
  "posts_count": 4,
  "raw": "The 3.5 release ships today with **faster search**.",
  "readers_count": 39,
  "reads": 40,
  "reply_count": 3,
  "reply_to_post_number": null,
  "score": 82.4,
  "staff": true,
  "topic_id": 42,
  "topic_slug": "release-3-5-is-out",
  "topic_title": "Release 3.5 is out",
  "trust_level": 4,
  "updated_at": "2026-08-30T09:12:44.000Z",
  "user_id": 3,
  "username": "ada",
  "version": 1,
  "wiki": false,
  "yours": true
}
```

### Set topic status

Close, archive, unlist or pin a topic, or undo any of those: pick the status and whether to turn it on or off. Pinning can be given an expiry. 'Listed' off hides the topic from topic lists without deleting it.

**Inputs**

- Topic (`topic_id`, text, required): The topic to act on: its ID, or its URL on the forum such as https://forum.example.com/t/welcome/8.
- Status (`status`, text, required): Which status to change. One of: `closed` (Closed (no new replies)), `archived` (Archived (frozen)), `visible` (Listed (visible in topic lists)), `pinned` (Pinned in its category), `pinned_globally` (Pinned across the whole forum).
- Turn it on (`enabled`, true/false, required): Tick to apply the status (close, archive, list or pin the topic); untick to remove it.
- Pinned until (`until`, date and time): When a pin should expire. Only used when pinning; leave empty to pin indefinitely.

**Outputs**

- `enabled` (true/false)
- `status` (text)
- `success` (text)
- `topic_id` (number)
- `topic_status_update` (text)

**Example output**

```json
{
  "enabled": true,
  "status": "closed",
  "success": "OK",
  "topic_id": 42,
  "topic_status_update": null
}
```

### Update category

Rename a category, change its colours or slug, or move it under another category. Only the fields you fill in change; the rest are read from the category and sent back as they are. Needs an admin API username.

**Inputs**

- Category (`category_id`, text, required): The category to act on. Pick one, or paste a category ID or its URL on the forum.
- Name (`name`, text): A new name.
- Colour (`color`, text): The category's colour as six hex digits, with or without a leading #, such as 0088CC.
- Text colour (`text_color`, text): The colour of the category's name on its badge, as six hex digits. Usually FFFFFF on a dark colour.
- Parent category (`parent_category_id`, text): Make this a subcategory of the chosen category. Leave empty for a top-level category.
- Slug (`slug`, text): The part of the category's URL after /c/. Leave empty and Discourse derives one from the name.

**Outputs**

- `all_topics_wiki` (true/false)
- `allow_badges` (true/false)
- `allow_global_tags` (true/false)
- `allowed_tag_groups` (list)
- `allowed_tags` (list)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `color` (text)
- `custom_fields` (object)
- `default_list_filter` (text)
- `default_top_period` (text)
- `default_view` (text)
- `description` (text)
- `description_excerpt` (text)
- `description_text` (text)
- `email_in` (text)
- `email_in_allow_strangers` (true/false)
- `emoji` (text)
- `has_children` (true/false)
- `icon` (text)
- `id` (number)
- `locale` (text)
- `mailinglist_mirror` (true/false)
- `minimum_required_tags` (number)
- `name` (text)
- `notification_level` (number)
- `num_featured_topics` (number)
- `parent_category_id` (number)
- `permission` (number)
- `position` (number)
- `post_count` (number)
- `read_restricted` (true/false)
- `search_priority` (number)
- `show_subcategory_list` (true/false)
- `slug` (text)
- `sort_order` (text)
- `style_type` (text)
- `subcategory_count` (number)
- `subcategory_list_style` (text)
- `text_color` (text)
- `topic_count` (number)
- `topic_featured_link_allowed` (true/false)
- `topic_template` (text)
- `topic_url` (text)
- `uploaded_background` (object)
- `uploaded_logo` (object)

**Example output**

```json
{
  "can_delete": false,
  "can_edit": true,
  "color": "0088CC",
  "description": "News from the team.",
  "description_text": "News from the team.",
  "has_children": false,
  "id": 5,
  "name": "Announcements",
  "notification_level": 1,
  "parent_category_id": null,
  "permission": 1,
  "position": 1,
  "post_count": 87,
  "read_restricted": false,
  "slug": "announcements",
  "subcategory_count": 0,
  "text_color": "FFFFFF",
  "topic_count": 12,
  "topic_url": "/t/about-the-announcements-category/9"
}
```

### Update post

Replace a post's body with new Markdown, optionally noting why. Editing a topic's first post edits the topic's body. Editing another member's post needs a staff API username.

**Inputs**

- Post ID (`post_id`, text, required): The post to act on, as the 'id' a create, get-topic or list step returned. This is the post's own ID, not its number within the topic.
- Body (`raw`, text, required): The post body, in Markdown. Discourse enforces a minimum length (20 characters by default).
- Edit reason (`edit_reason`, text): Why it was edited, shown in the post's edit history.
- Don't bump the topic (`bypass_bump`, true/false): Edit without moving the topic to the top of the list. Needs a staff API username.

**Outputs**

- `actions_summary` (list)
- `admin` (true/false)
- `avatar_template` (text)
- `bookmarked` (true/false)
- `can_delete` (true/false)
- `can_edit` (true/false)
- `can_recover` (true/false)
- `can_wiki` (true/false)
- `category_id` (number)
- `cooked` (text)
- `created_at` (text)
- `deleted_at` (text)
- `display_username` (text)
- `edit_reason` (text)
- `excerpt` (text)
- `hidden` (true/false)
- `id` (number)
- `incoming_link_count` (number)
- `moderator` (true/false)
- `name` (text)
- `post_number` (number)
- `post_type` (number)
- `post_url` (text)
- `posts_count` (number)
- `primary_group_name` (text)
- `quote_count` (number)
- `raw` (text)
- `readers_count` (number)
- `reads` (number)
- `reply_count` (number)
- `reply_to_post_number` (number)
- `score` (number)
- `staff` (true/false)
- `topic_html_title` (text)
- `topic_id` (number)
- `topic_slug` (text)
- `topic_title` (text)
- `truncated` (true/false)
- `trust_level` (number)
- `updated_at` (text)
- `user_deleted` (true/false)
- `user_id` (number)
- `user_title` (text)
- `username` (text)
- `version` (number)
- `wiki` (true/false)
- `yours` (true/false)

**Example output**

```json
{
  "admin": true,
  "avatar_template": "/user_avatar/forum.example.com/ada/{size}/3_2.png",
  "can_delete": true,
  "can_edit": true,
  "category_id": 5,
  "cooked": "<p>The 3.5 release ships today with <strong>faster search</strong>.</p>",
  "created_at": "2026-08-30T09:12:44.000Z",
  "deleted_at": null,
  "display_username": "Ada Lovelace",
  "edit_reason": null,
  "hidden": false,
  "id": 731,
  "moderator": false,
  "name": "Ada Lovelace",
  "post_number": 1,
  "post_type": 1,
  "post_url": "/t/release-3-5-is-out/42/1",
  "posts_count": 4,
  "raw": "The 3.5 release ships today with **faster search**.",
  "readers_count": 39,
  "reads": 40,
  "reply_count": 3,
  "reply_to_post_number": null,
  "score": 82.4,
  "staff": true,
  "topic_id": 42,
  "topic_slug": "release-3-5-is-out",
  "topic_title": "Release 3.5 is out",
  "trust_level": 4,
  "updated_at": "2026-08-30T09:12:44.000Z",
  "user_id": 3,
  "username": "ada",
  "version": 1,
  "wiki": false,
  "yours": true
}
```

### Update topic

Rename a topic, move it to another category, or both. To change its body, update its first post with 'Update post'.

**Inputs**

- Topic (`topic_id`, text, required): The topic to act on: its ID, or its URL on the forum such as https://forum.example.com/t/welcome/8.
- Title (`title`, text): A new title.
- Category (`category_id`, text): The category to move it to.

**Outputs**

- `fancy_title` (text)
- `id` (number)
- `posts_count` (number)
- `slug` (text)
- `title` (text)

**Example output**

```json
{
  "fancy_title": "Release 3.5 is out",
  "id": 42,
  "posts_count": 4,
  "slug": "release-3-5-is-out",
  "title": "Release 3.5 is out"
}
```
