Could usernames be included in user_badge webhook payload?

Any chance the user_badge webhooks could include username along with user_id? Currently the payload for a user_badge event looks like this:

{
  "user_badge": {
    "id": 123456,
    "granted_at": "2026-09-25T14:54:42.073Z",
    "created_at": "2026-09-26T05:34:12.965Z",
    "post_id": 234567,
    "post_number": 1,
    "badge_id": 123,
    "user_id": 456,
    "granted_by_id": -1,
    "topic_id": 56789
  }
}

Getting the username for the user_id (and granted_by_id if it’s not -1) requires an additional call to /admin/users/{user_id}.json, which not only requires additional requests, but also requires admin privileges as far as I can tell.

Is there a way to get username for a given a user_id using an API key without needing admin privileges?

I’m creating an external service that I was hoping to trigger when specific badge(s) are granted; however, it needs the username and badge webhooks only returns user IDs. :confused:

FWIW, my workaround for non-standard webhooks or when I need additional data is to do it via Workflows and then send that to n8n.

Fwiw, fetching username from user id is just one API call away, unless you’re manually granting thousands of badges in an instant, you should be fine with the default API limits.

Thanks! I’ll look into Workflows.

That’s great to hear! Could you please provide details about that one API call that isn’t /admin/users/{user_id}.json (which requires admin privileges)? I wasn’t able to find an endpoint to do this with an API key that didn’t require admin privileges.

What’s the issue with an admin API key? This is supposed to be a background job ig?

Principal of Least Privilege. This external service will be running on another server and only needs read access to Discourse to do it’s job. The fewer master keys floating around across infrastructure, the better.

This brings up the interesting point of why isn’t there a public-facing endpoint to get a user by id that shows only public fields, if login_required is not selected. It would be useful, no? I wonder why it was not made. Or maybe only logged in users could get such a privilege, but either way, there should be some way to access it without the use of the admin endpoint…

@burke A more onerous workaround would be to look at /groups/trust_level_0/members.json (or any more specific group) and find the user by their id, since that also contains the username.

This is because for all matters and purposes user IDs are essentially an internal convention in discourse and we are expected to rely on usernames that are much more prominent across the board.