How to reverse engineer the Discourse API

(Sam Saffron) #1

Discourse is backed by a complete JSON api. Anything you can do on the site you can also do using the JSON api.

Many of the endpoints are properly documented in the discourse_api gem, however some endpoints lack documentation.

To determine how to do something with the JSON API here are some steps you can follow.

Example: recategorize a topic.

  • Go to a topic and start editing a category:

  • Open Chrome dev tools, switch to the Network tab, select XHR filter:

  • Perform the operation

  • Look at preview as well to figure out the results

  • You now have all the info you need.
  1. The endpoint is

  2. Payload is passed using a PUT

  3. The parameter sent is: category_id: 5

Equip with this information you can make your own calls using your favorite programming language, all you need to do is add api_username and api_key to parameters to the request.

They can be generated using the API admin tab.

Discourse API Documentation
Create group via API
Assign group permission to a category via API
Delete Post from a Topic Using discourse API
How do I get all posts from a specific category?
Is there an API for changing a password?
Integrate dynamic code to template?
API - Can you add a user to a group?
Discourse API Documentation Released!
API: Getting all posts in a topic
Good resources for understanding the API?
Get list of wiki editors
Custom permalinks
Internal server error setting tags via the api
API for changing category groups
Cannot update group owners via Ruby or REST API
API documentation error?
Incoming Web Hooks
Pinning topics not at top of latest response
/directory_items.json API returns wrong link for next page
Data Explorer Plugin
How do I set-up this workflow? Membership form with Payment > Discourse Invite
Posting a new topic via API
Update theme with API
Top Referred Topics and Trending search via API
API call to get all site_texts
Is there a way to check validity of a new username via the API before actually trying to register?
Specify user by external id
Create sub-categories via Postman
Trust Level Requirements from API
Check_username api endpoint seems to not work correctly
Invite user to topic by email via APi
Create post via the api with tags and category
Group and Category customization
No way to get period stats?
API - Get topics a user is active in
How to remove someone from a Message?
How to get uploaded image url using the Discourse API?
What is the Timing of Formal Discourse REST API?
How can we create post/topic in Discourse using API
Discourse API Documentation
Discourse API Documentation
API to call any SQL: either pass SQL directly OR predefine in GUI and give it a nickname
Discourse API Documentation
API Error: You are not permitted to view the requested resource
Integrating Discourse with a larger social network app?
Discourse API Documentation
Is there a way to see hourly post data?
Exclude / Suppress (Automatically) Closed Topics from the Homepage?
Api documentation on creating private forums
Api documentation on creating private forums
Problem creating a category using the API
How to remove tags via API
Seeding a new forum by creating users and content
Open composer for existing topic/personal message via URL
Discourse always posts in general using API
User API only shows 3 badges
Unformatted text gets formatted if submitted by API
API call to unmask all emails
Approving an already-existing user through API?
API for Category based notification level update
Adding user to group from API gets "BAD CSRF"
Correct method for updating category group permission level via API
Bulk change setting - want to enable accepted solution for multiple subcategories
Assign topics or messages when created via API
How to mark Topic or Notification as "Read = true"
API GET for Category User notification_level
Change ownership through the API?
Calling POST on /posts.json returns null
Setting a category to use the solved plugin via console
Custom Query on static web page
Bulk revert edits (bulk undone edits)
Get "badge-notification" from API?
How should I get the raw text of a single post
Post unread count clear api
Admin forum statistics for posts/topics
Leaderboard Plugin
Data Explorer Queries accessible to public
Remove users script either via API or PG available?
Getting who liked a post from the API
How can i set posting option through api?
How can i rename a group with the help of discourse api?
(Arpit Jalan) #2

Here is the Ruby code to make API request for “recategorizing a topic” that @sam reverse engineered in first post:

require 'net/http'
require 'uri'


def send_request

    url = URI.parse(INSTANCE_URL)
    request =
    request.set_form_data({'api_username' => API_USERNAME, 'api_key' => API_KEY, 'category_id' => 5})
    http =, url.port)
    response = http.request(request)

    if response.code == '200'
      puts "Success!"
      puts "Error"


(Arpit Jalan) #3

Sent a PR to support “recategorizing a topic” from discourse_api gem:

After this change is merged, you can simply do:

client.recategorize_topic(topic_id: 108, category_id: 5)

where topic_id is the id of topic to recategorize, and category_id is the id of new category.

(Erik Chan) #4

Trying to follow these directions to figure out how to change the notification settings of a user…

This is the operation

This is the preview of the result

This is the code I’m testing:

instance_url = '' + '41' + '/notifications.json'
url = URI.parse(instance_url)
request =
request.set_form_data({'api_username' => client.api_username, 'api_key' => client.api_key, 'user' => "11f56d90b7ae45ee8925c7d23712b1a4", 'notification_level' => 3})
http =, url.port)
response = http.request(request)

if response.code == '200'
  puts "Success!"
  puts "Error"

I get a 200 success response. But the notification setting didn’t change. Any suggestions?

(Erik Chan) #5

Looking at the discourse code for setting notifications:

def set_notifications
category_id = params[:category_id].to_i
notification_level = params[:notification_level].to_i

CategoryUser.set_notification_level_for_category(current_user, notification_level, category_id)
render json: success_json


I guess the question I have is whether this is possible? The notification level and the category is in the request but ‘current_user’ is required in ‘set_notification_level_for_category’

(Kane York) #6

The change will take effect as the api_username (it goes into current_user if successful).

(Erik Chan) #7

perfect! thanks, that solves the problem.

(Richard Phillips) #8

Thanks for this - I might be missing something but when I follow these instructions I only see posts to /messagebus/ - so can’t work out the correct apil url.

Am trying to consume API from php and need to add more methods.

(Kane York) #9

Make sure that you open the network tab before taking any actions, and that you aren’t using a request filter left over from before.