# API invite with group\_names param returns 403 for group-owner user unless they are admin

**URL:** https://meta.discourse.org/t/api-invite-with-group-names-param-returns-403-for-group-owner-user-unless-they-are-admin/410808
**Category:** Bug
**Tags:** rest-api, invites
**Created:** [August 24, 2026, 4:40pm UTC](https://meta.discourse.org/t/api-invite-with-group-names-param-returns-403-for-group-owner-user-unless-they-are-admin/410808 "2026-08-24T16:40:25Z")
**Posts on this page:** 1
**Showing post:** 1

<div class="post-metadata">

### Author: ![Lew\_Grothe](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lew_grothe/32/337776_2.png) [@Lew\_Grothe](https://meta.discourse.org/u/Lew_Grothe)
#### Post date: [August 24, 2026, 4:40pm UTC](https://meta.discourse.org/t/api-invite-with-group-names-param-returns-403-for-group-owner-user-unless-they-are-admin/410808/1 "2026-08-24T16:40:25Z")

</div>

**Summary**

A non-admin user who is an **owner** of a Discourse group can successfully invite new members with that group assigned through the web UI invite dialog. The identical action via the REST API (`/invites.json`, Global-scope API key, correct `Api-Username`) returns a 403 `invalid_access` — but only when `group_names`/`group_ids` is included in the payload. This occurs regardless of whether `group_names` is passed as a plain string (e.g. `"group_names": "my-group"`) or as an array (e.g. `"group_names": ["my-group"]`) — both formats produce the identical 403.

Critically, **granting the user Moderator status does not fix the API call — only granting full Admin does** , even though Moderator is sufficient for every other tested scenario (web UI, non-grouped API invite).

**Environment**

- Discourse version: [fill in — `Admin → Upgrade` page]
- API key type: Global scope, `Api-Username` = the test user’s exact username

**Steps to reproduce**

1. Create non-admin, non-moderator user (`<userid>`), make them **owner** of group `<group_name>`.
2. Web UI, as `<userid>`: invite with no group → succeeds. Invite with `<group_name>` assigned → succeeds.
3. API, as `<userid>` (Global-scope key, `Api-Username=<userid>`):
  - `POST /invites.json` with no `group_names` → succeeds.
  - `POST /invites.json` with `group_names="<group_name>"` (string form) → **403 `invalid_access`**.
  - `POST /invites.json` with `group_names=["<group_name>"]` (array form) → **403 `invalid_access`** (identical failure, both formats tested).

4. Promote `<userid>` to **Moderator**. Repeat step 3’s grouped API calls (both formats) → **still 403 `invalid_access`.**
5. Promote `<userid>` to **Admin**. Repeat step 3’s grouped API calls, same key, same payloads → **succeed.**

**Expected behavior**

Since group ownership alone is sufficient permission for a non-staff user to assign that group on invite via the web UI, the API — authenticated as the same user via `Api-Username` — should honor the same permission. At minimum, Moderator (which is staff) should not behave identically to a non-privileged user here; the fact that Moderator fails identically to no-role, and only Admin succeeds, suggests the API code path checks `user.admin?` specifically rather than group ownership or even general staff status (`user.staff?`, which is true for moderators).

**Actual behavior**

The API 403s on any grouped invite (string or array parameter format) unless the acting user is a full Admin. Group ownership (verified working via web UI) and Moderator/staff status (verified via direct promotion test) are both insufficient for the API path, despite either being sufficient through the web UI or for the ungrouped API case.

**Question for the Discourse team**

Does the API-authenticated invite-with-group code path require `user.admin?` explicitly, rather than checking group ownership or `user.staff?` the way the web UI / session-authenticated path does? If so, is this intentional (undocumented API-specific restriction) or a bug where the API guardian check diverges from the web guardian check for this action?

Happy to provide full request/response logs (key redacted) on request.

---

_[View the full topic](https://meta.discourse.org/t/api-invite-with-group-names-param-returns-403-for-group-owner-user-unless-they-are-admin/410808)._
