Maybe we’re building the same thing although mine’s only somewhat headless.
I suspect that there isn’t, and that it’s by design.
I’ve been wondering about the same thing, but I think for my case that it will be fine - I’m not trying to hide Discourse.
One thing to keep in mind with User api keys vs admin All User api keys is that by default they have different rate limits applied to them: Available settings for global rate limits and throttling.
user api rate limit:
DISCOURSE_MAX_USER_API_REQS_PER_MINUTE
: default 20
DISCOURSE_MAX_USER_API_REQS_PER_DAY
: default 2880
admin api rate limit:
DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE
: 60
If your application is connecting to a self-hosted Discourse site, you can likely override the admin api rate limit. If your application is connecting to hosted Discourse instances, the user api rate limits offer a lot more flexibility. With the admin api rate limit you end up having to put all requests into a rate limited queue.
Edit: instead of using the User API Keys Specification for generating the keys, you can use an admin API key for generating user API keys. That gets around the issue of user’s having to approve the app.
Note that the key posted below is for my localhost domain, so there’s no risk in posting it.
unescaped key params: {key:description:sally} {key:username:sally} {key:scopes:[scope_id:topics:write]} {key:scopes:[key:write]} {key:scopes:[name:write]} {key:scopes:[params:[topic_id]]} {key:scopes:[urls:[/posts (POST)]]} {key:scopes:[selected:true]}
❯ curl -X POST "http://localhost:4200/admin/api/keys" \
-H "Api-Key: $api_key" \
-H "Api-Username: system" \
-H "Content-Type: application/json" \
-d $json
{"key":{"id":29,"key":"f5c6307b51dd2882bde525dc9775fe7504b55c93fa40177b650f9e6b77a9d25b","truncated_key":"f5c6","description":"sally","last_used_at":null,"created_at":"2024-06-02T00:44:19.944Z","updated_at":"2024-06-02T00:44:19.944Z","revoked_at":null,"user":{"id":3,"username":"sally","avatar_template":"/user_avatar/127.0.0.1/sally/{size}/58_2.png"},"api_key_scopes":[{"resource":"topics","action":"write","parameters":["topic_id"],"urls":["/posts (POST)"],"allowed_parameters":{},"key":"write"}]}}
In either case, your left with an API key that needs to be managed somehow. I’m assuming encrypted and saved to a database.