Discourse API Documentation

Discourse API

Please view the Discourse API Documentation site for detailed info:


:warning: Deprecation Warning!

On April 6th, 2020 we dropped support for all non-HTTP header based authentication (excluding some rss, mail-receiver, and ics routes). This means that API requests that have an api_key and api_username in the query params or in the HTTP body of the request will soon stop working. Please see the example cURL request below for how to update your API requests to use the HTTP headers for authentication.

The Content-Type can be set to “application/x-www-form-urlencoded”, “multipart/form-data” or “application/json”.

Here is an example POST request via cURL:

curl -X POST "" \
-H "Content-Type: multipart/form-data;" \
-H "Api-Key: 714552c6148e1617aeab526d0606184b94a80ec048fc09894ff1a72b740c5f19" \
-H "Api-Username: discourse1" \
-F "name=89853c20-4409-e91a-a8ea-f6cdff96aaaa" \
-F "color=49d9e9" \
-F "text_color=f0fcfd"

Here is an example of what the API Documentation site looks like:

Consuming the API

You can consume the API using cURL commands, but we recommend using the discourse_api gem so that you can use Ruby.

Reverse engineering API endpoints

Not every endpoint is documented, but you can see an example API request and response for any endpoint by follow this guide:

API: Can I authenticate without putting the key in the URL?
Online User API?
Deeply integrating Discourse into website
Discourse Add Group API
How can I update trust level via SSO site
Do we have any API or way to get latest post details for a particular Topic in discourse?
Update current user fields through JavaScript?
API call to watch categories and tags
Using the Discourse API Ruby Gem
Use discourse_post_id to get single topic data from API
JSON API, get topics sorted by created_at
Quick Messages Plugin
How to get notifications via the API
Locations Plugin
Is there is any open API for getting similar topic in discourse?
What determines the order of frequent poster icons in the topic list?
Working with different needs in raw/cooked content
What is Discourse Blog built with?
What is correct aproach to update topic via ajax?
How to Create a Script to "Bulk Remove" from a Group?
Display username when login in banner
Possible for admins to create bookmarks for users?
API: Can I authenticate without putting the key in the URL?
Dev Category sidebar
RSS Feed Stopped Working?
Logout POST Request
Which CMS for Discourse
Discourse API - Unable to query certain endpoints
Discourse Trust Levels for Discord
How to run Data Explorer queries with the Discourse API
WP Discourse plug in being odd
How to update mail-receiver to the release version
All API calls now getting "You are not permitted to view the requested resource"
Drupal SSO generates incorrect user sessions
Authentication using HTTP headers
'BAD CSRF' while creating a new post
403 Error during multiple API calls
Prometheus exporter plugin for Discourse
/admin/users/1/log_out route error
Help with Authenticating user via API
Delete user avatar by API
Acess-Control-Allow-Headers CORS Error with API after updating discourse
How do I send a topic id just created?
What is Discourse API?
Can Discourse API link with Obsidian?
Find a user by their identity provider 'external ID'
Bot writer's tip: Processing every post
Access reports JSON data via Pipedream
Help me troubleshoot my Discourse SSO
Bulk undelete topics help 😟
Best Practise for Using a Raspberry PI as Bot for Posting Updates in Discourse
Getting ["BAD CSRF"] when updating topic via API [python]
"BAD CSRF" when executing PUT using API, curl, and PHP
Creating alternate user directory
Creating a new topic on behalf of a user
How can I update trust level via SSO site
Questions about support with hosted Discourse
Synchronizing Changes for SSO users
Shopify Integration
[Announce] Search & replace / batch process Discourse posts
API Error: You are not permitted to view the requested resource
Migrating from Jive Clearspace to Discourse
Can an admin change a user's email address?
How to get uploaded image url using the Discourse API?
Can't send PM via API (HTTPUnprocessableEntity 422)
How to contribute to the Discourse API Docs
Swagger, WADL or similar for the REST API?
Vague error from clicking on a tag link on this site
Work Around to posting
Discourse dislike Api?
A list of server-side functions for weekend/novice Discourse developers?
Api documentation on creating private forums
Seeding a new forum by creating users and content
How to implement Discourse with an already built Rails project
Using the API, can't PUT to topic unless slug is on the URL
Using the API, can't PUT to topic unless slug is on the URL
Incoming webhooks (Incoming into Discourse)
Managing site customization via API
Discourse API Documentation Using RAML
Is it possible to mount a playable video game into a discourse forum?
How to upload bulk post
Interact with discourse from Python?
How to update profile information via API

Now that this API deprecation warning:

has had several months to simmer, I wanted to let everyone know that we will be fully deprecating API credentials in query parameters on April 6th, 2020. It will be available to self-hosters shortly thereafter when the next beta release is out.

During November 2019 we released an update to your admin dashboard that would appear if it detected this deprecated API authentication method. Please check your admin dashboard for this message and make the appropriate changes to any API integrations you may have. If you do not see this message you either have an API integration that triggers less than once every 24 hours or you don’t have any affected API integrations and have nothing to update.

We are making this change in an effort to further increase the security of all Discourse sites by removing the support of API authentication credentials inside of query parameters and requiring that authentication credentials are passed inside of HTTP Headers.

The only API endpoints that will not be affected and will continue to have support for credentials in query parameters will be requests to RSS feeds and the Mail Receiver endpoint.


Running through this change - it doesn’t look like the Api-Key or Api-Username headers have been added to the Access-Control-Allow-Headers setting - https://github.com/discourse/discourse/blob/master/config/initializers/008-rack-cors.rb

Once this deprecation comes in, the API will no longer be accessible programmatically - at least in the way we’re currently using it.

Am I missing something obvious here?

Duplicate here: API CORS Headers Incorrect - #2 by jessicat

Although this was closed by @david I disagree with his explanation. There are scenarios where we want to generate an API key on behalf of a user, without them having to get approval from the user. In our use case, the API key generation should very much remain ‘hidden’ from the user, and hence our only choice is to use the Admin API keys, rather than User API keys.

I understand it’s not as simple as enable CORS by default for the Admin API headers, but this should at least be configurable in the same way that CORS origins are…

1 Like

The admin API keys you’re providing to the browser clients bypass some significant ratelimiting. (Not all.) Making these available to an end-user browser is almost universally a mistake.


I appreciate this isn’t ideal - but what’s the alternative in our situation where we need to programmatically generate user specific API keys?

These keys also don’t provide ‘admin access’ from what we’ve experienced.

I can think of two possible ways forward from our perspective:

  • Addition of programmatic generation of User API Keys
  • Addition of scoping to Admin generated API Keys

Right now, rate limiting isn’t something we’re too worried about as we mostly handle that at the server layer, not the application layer. And as you can imagine, since we’re programmatically generating API keys, we’re quite happy to programmatically revoke them as well. In general we cycle the API key on each session or end of day.

I’d love to move forwards with a solution that didn’t feel like a compromise or a hack though!

1 Like

Got this in my admin dashboard:

* We detected an API request using a deprecated authentication method. Please update it to use [header based auth](https://meta.discourse.org/t/-/22706). After updating this message may take 24 hours to disappear.

Also not sure if its somehow related to this, but sometimes i get a “connection not secure” Chrome warning when going through my forum. It happens randomly, not in all occasions. I see that the http://schema.org urls are the ones not going through https, but not sure how to fix all of this.

Forum URL: https://wmforum.geek.hr/

Any ideas?

1 Like

For the deprecated API request message, can you check your API keys in your admin dashboard /admin/api/keys and see when they were last used? Do you know what integrations might be using one of your API keys?


Example here: Kako da na sajt postavim ovakav brojač pregleda? - web dizajn - WM Forum - Forum za web majstore

The favicon loaded in this onebox is not loaded over https.



@blake Yeah i had some old API from year 2013. active, so i deactivated it. Was probably used to communicate with the WP Discourse plugin.


Ok added ico to authorized extensions and it looks like the problems are all gone now.

Thanks guys!


I’ve been getting warnings as well. The reason is webcal access from a calendar app. Will this still work after the April deadline?

1 Like

I believe @Falco is adding support for webcal links?


Update the wp-discourse plugin and follow the directions to set it back up again with a new api key :slight_smile:


Just to add – using a tool like Postman is fantastic and makes understanding and experimenting with the API very easy. However, I find Postman’s interface to be a little over-engineered and confusing for making simple calls. I prefer Insomnia (free, open source)-- much more simple and clear.


Hi guys, just started with Discourse 2 weeks ago and it’s a ride alright :slight_smile:.

I have an issue when i request /session/current.json … The curent_user_serializer fails with error

`NoMethodError (undefined method `can_send_private_messages_to_email?' for nil:NilClass)
/Users/stefanb/ab4/i-fikr-discourse/app/serializers/current_user_serializer.rb:118:in `can_send_private_email_messages'
  Rendering /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb (Duration: 1.0ms | Allocations: 729)
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (Duration: 5.1ms | Allocations: 6306)
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (Duration: 5.5ms | Allocations: 3873)
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (Duration: 3.9ms | Allocations: 5372)
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (Duration: 2.7ms | Allocations: 2816)
  Rendering /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (Duration: 2.8ms | Allocations: 3858)
  Rendered /Users/stefanb/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (Duration: 315.7ms | Allocations: 232803)

#<User id: 1, username: "sbrighiu", created_at: "2020-04-02 14:07:16", updated_at: "2020-04-09 11:59:13", name: nil, seen_notification_id: 4, last_posted_at: "2020-04-09 11:59:13", password_hash: [FILTERED], salt: "< &- & >", active: true, username_lower: "sbrighiu", last_seen_at: "2020-04-10 20:03:31", admin: true, last_emailed_at: nil, trust_level: 1, approved: true, approved_by_id: -1, approved_at: "2020-04-02 14:07:20", previous_visit_at: "2020-04-10 15:01:51", suspended_at: nil, suspended_till: nil, date_of_birth: nil, views: 0, flag_level: 0, ip_address: #<IPAddr: IPv4:>, moderator: false, title: nil, uploaded_avatar_id: nil, locale: nil, primary_group_id: nil, registration_ip_address: nil, staged: false, first_seen_at: "2020-04-02 14:37:52", silenced_till: nil, group_locked_trust_level: nil, manual_locked_trust_level: nil, secure_identifier: nil>

Any ideas why this happens? Not a ruby guy :slight_smile: … also maybe why it happened?

Is there a changelog for the ruby API?

I see 0.39.1 is latest, but there are only releases up to 0.38.0.

We’re on 0.31.0 right now and started seeing 404’s on April 7th with the groups_add API, so I’m guessing this has to do with this deprecation.

Will updating to 0.39.1 be sufficient to remedy?

Also shortly after this we started seeing pg bouncer errors in the logs…

Appreciate any thoughts!

The changelog can be found here: https://github.com/discourse/discourse_api/blob/master/CHANGELOG.md

0.39.1 is on rubygems: discourse_api | RubyGems.org | your community gem host

Yes, it should be

This won’t be related to the API usage. It looks like a small network issue, but it has resolved itself (“Master server is active. Reconnecting…”)


Oh, duh, donno how I missed that!

Yep! Our integration is working again, thanks so much @david!


Having the same problem with a forum that was set up 5 years ago, and has incomplete documentation on the integrations.

What kinds of integrations would be possible candidates for this error? Would Twitter login be an example? (Though that’s a set of key/secrets from Twitter entered into Discourse, not the other way around). Maybe something will jog the memory.

All I see under API -> API is Created and Last used (the description is blank). Would it be possible to display some identifying information in that table (or at least obtain it from logs, like the IP of the last API request)?

1 Like

We don’t have anything in the admin UI that would show you what was using that api key. You will need to look at your nginx logs and parse them for the api query parameters too see what endpoints are being used.