EDA.API.Role (EDA v0.4.0)

Copy Markdown View Source

REST API endpoints for Discord guild roles.

All functions return {:ok, result} or {:error, reason}.

Summary

Functions

Creates a role in a guild.

Gets roles for a guild.

Gets the number of members carrying each role in a guild.

Modifies guild role positions.

Functions

create(guild_id, params \\ [], opts \\ [])

@spec create(String.t() | integer(), keyword() | map(), keyword()) ::
  {:ok, map()} | {:error, term()}

Creates a role in a guild.

delete(guild_id, role_id, opts \\ [])

@spec delete(String.t() | integer(), String.t() | integer(), keyword()) ::
  :ok | {:error, term()}

Deletes a guild role.

list(guild_id)

@spec list(String.t() | integer()) :: {:ok, [map()]} | {:error, term()}

Gets roles for a guild.

member_counts(guild_id)

@spec member_counts(String.t() | integer()) ::
  {:ok, %{required(String.t()) => non_neg_integer()}} | {:error, term()}

Gets the number of members carrying each role in a guild.

Returns a map of role ID to member count.

Two things to know, both confirmed against a live guild (2026-09-19):

  • the @everyone role is absent from the result — its ID equals the guild ID, and every member carries it, so Discord omits it. Expect one fewer entry than list/1 returns;
  • the counts overlap. A member holding three roles is counted in all three, so the values sum to more than the guild's member_count (2739 against 528 on the guild probed).

Why not count from the cache?

The traditional approach in other libraries is to filter cached members — discord.js's Role.members, JDA's getMembersWithRoles/1. EDA can do the same with EDA.Cache.members/1, but that needs the privileged :guild_members intent and a fully chunked member cache (config :eda, chunk_members: true). This endpoint needs neither.

Measured against a live guild with a complete member cache (2026-09-19), the two agree exactly: 0 divergences over 56 roles, 2739 assignments either way. But counting from the cache saw only 52 roles against the endpoint's 56 — roles with zero members are absent from a cache-derived tally and present here. If you are listing every role with its count, that difference is the whole point.

discord.js exposes the same endpoint as guild.roles.fetchMemberCounts() and documents the same @everyone exclusion.

Examples

{:ok, counts} = EDA.API.Role.member_counts(guild_id)
#=> {:ok, %{"938496731396599808" => 179, "964090281647542342" => 272}}

Map.get(counts, role_id, 0)

modify(guild_id, role_id, payload, opts \\ [])

@spec modify(String.t() | integer(), String.t() | integer(), map(), keyword()) ::
  {:ok, map()} | {:error, term()}

Modifies a guild role.

modify_positions(guild_id, positions)

@spec modify_positions(String.t() | integer(), [map()]) ::
  {:ok, [map()]} | {:error, term()}

Modifies guild role positions.

set_colors(guild_id, role_id, colors, opts \\ [])

@spec set_colors(
  String.t() | integer(),
  String.t() | integer(),
  EDA.Role.Colors.t() | map(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Sets a role's colours.

Accepts an EDA.Role.Colors struct or a plain map. Sends only the colors object, never the deprecated color field — matching discord.js, whose setColors builds the same payload.

Discord enforces the holographic triple whenever tertiary_color is present, so build that case with EDA.Role.Colors.holographic/0 rather than by hand.

Requires an eligible guild

Setting anything other than a solid colour returns HTTP 403 with code 670006, "Missing guild feature" (EDA.Error.missing_guild_feature/0) on a guild that is not eligible — observed on a boost-tier-0 guild, 2026-09-19. There is nothing to check first: ENHANCED_ROLE_COLORS was absent from the features array of every guild probed, including one that already had seven gradient roles. Attempt the call and handle 670006.

Options

  • :reason — audit log reason

Examples

EDA.API.Role.set_colors(guild_id, role_id, EDA.Role.Colors.gradient(0xFF0000, 0x00FF00))
EDA.API.Role.set_colors(guild_id, role_id, EDA.Role.Colors.holographic(), reason: "event")
EDA.API.Role.set_colors(guild_id, role_id, %{primary_color: 0x5865F2})