Access via Discourse API, key and/or user rejected

AI-generated summary

A Discourse moderator, tflidd, is trying to access their forum via the Discourse API using a Python library called pydiscourse. However, they’re encountering an error stating that their API username or key is invalid.

tflidd has generated a 32-character API key and set up the necessary permissions, but is still unable to access the API.

Arkshine points out that the issue is due to the pydiscourse library being designed for Admin API keys, whereas tflidd has generated a Client API key.

Arkshine provides a solution using curl with the API-User-Key and API-User-Username headers, which tflidd confirms works.

tflidd also notes that the API endpoints remain the same and suggests that the documentation should mention how to authenticate with both Admin and Client API keys.

Additionally, tflidd provides a workaround for using the Client API key with the pydiscourse library by modifying the request headers.

As a moderator, I’d like to use the API for a discourse forum. Normally it was activated and I manage to get a API key. I used this script:

I manage to retrieve a key which is 32 characters long (is that right?), and in the security settings of my account, the app shows with these permissions:

Read all
Write all
Live updates
Push notifications to external services
Read and clear notifications
Read user session info
Create a one-time login token

That looks quite good. However, when I try to access through a script with:

from pydiscourse import DiscourseClient

client = DiscourseClient(
        'https://forum.example.com',
        api_username='tflidd',
        api_key='388b79103056fede1d3223dae032df99')

client.user("tflidd")

It is a python library, so I suppose it should work. The api_key has this specific format, it is not the actual key. I get the error that either the username or the api key are not valid.

Do I use my username or the app name?
Is the API key at least the right format, perhaps decrypting something went wrong?

If I use curl like here (Discourse-user-notes API - #4 by codetricity):

curl https://forum.example.com/t/95783.json\ -H 'Api-Key: 388b79103056fede1d3223dae032df99'\ -H 'Api-Username: tflidd'

I get also an error:
{"errors":["You are not permitted to view the requested resource. The API username or key is invalid."],"error_type":"invalid_access"}

If I open the same URL with the json in my browser where I am logged in the web browser shows the right json object. So the topic exists and I have permissions to access it (this was even a public one).

I am just moderator, no direct admin access. I could ask for more info from the logs, if you have pointers what to look for.

In case it matters, the installed version is: 3.2.0.beta4-dev

The DiscourseClient python library is designed to work with an Admin API key (Admin → API).
What you generate from generate_api_key is a Client API key.

You need to pass API-User-Key and API-User-Username headers instead.
For example:

curl https://forum.example.com/t/95783.json -H 'Api-User-Key: 388b79103056fede1d3223dae032df99' -H 'Api-User-Username: tflidd'`

:+1: this works, you don’t know how much time I spent on this.

But the API endpoints are the same described here

?

(if yes, it would be great to mention not only how to authenticate with the admin API key but also mention the client API key)

For the pydiscourse client, there is a hacky workaround to use a different header:

from pydiscourse import DiscourseClient

client = DiscourseClient(
        'https://forum.example.com',
        api_username='tflidd',
        api_key='388b79103056fede1d3223dae032df99')

headers = {
            "Accept": "application/json; charset=utf-8",
            "User-Api-Key": '388b79103056fede1d3223dae032df99',
            "User-Api-Username": 'tflidd',
        }

slug = "abc"
topic_id = 1234

client.topic(slug=slug, topic_id=topic_id, override_request_kwargs=override_request_kwargs)