Invites¶
An invite is a code that admits an account into a guild.
Get invite is the only route here that needs no credential. Discovery covers joining a public guild without an invite.
Guild invites only
Every invite on TEBHOS is a guild invite (type 0). Invites for group direct messages are not currently created by the API.
Invite object¶
The public representation of one invite, returned by Get invite.
Structure¶
| Field | Type | Description |
|---|---|---|
| code | string | The code that identifies the invite |
| type | integer | Invite type, always 0 |
| guild | partial invite guild object | The guild the invite admits into |
| channel | partial invite channel object | The channel the invite points at |
| inviter | ?object | Always null in this representation |
| member_count | integer | The member count of the guild |
| presence_count | integer | The approximate number of online members (0 when unavailable) |
| expires_at | ?ISO8601 timestamp | When the invite stops resolving, or null when it never expires |
| temporary | boolean | The temporary flag the invite was created with |
The channel is the invite's stored channel. When the invite has none (a guild-wide invite or a custom invite URL), TEBHOS uses the guild's system channel, and otherwise the oldest text channel of the guild.
Example¶
{
"code": "a1b2c3d4",
"type": 0,
"guild": {
"id": "1489002177550843904",
"name": "Example guild",
"icon": null,
"banner": null,
"embed_splash": null,
"features": []
},
"channel": { "id": "1489002177550843905", "name": "general", "type": 0 },
"inviter": null,
"member_count": 412,
"presence_count": 87,
"expires_at": null,
"temporary": false
}
Partial invite guild object¶
| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the guild |
| name | string | The name of the guild |
| icon | ?string | The guild icon as a full URL |
| banner | ?string | The guild banner as a full URL |
| embed_splash | ?string | The background image used by invite cards (the guild's embed background, falling back to its banner) |
| features | array[string] | The guild's features, sorted |
Partial invite channel object¶
| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the channel |
| name | ?string | The name of the channel |
| type | integer | The channel type |
Invite types¶
| Value | Name | Description |
|---|---|---|
| 0 | GUILD | An invite that admits an account into a guild |
Invite metadata object¶
The management representation of an invite, returned by Create channel invite, List channel invites and List guild invites. Field names use camelCase.
Structure¶
| Field | Type | Description |
|---|---|---|
| id | string | Same as code |
| code | string | The invite code |
| serverId | snowflake | The ID of the guild |
| inviterId | snowflake | The ID of the account that created the invite (empty string when unknown) |
| inviterName | string | The display name of the creator (empty string when unknown) |
| inviter | ?object | {id, name, imageUrl} of the creator, or null |
| maxUses | ?integer | The maximum number of uses, or null for unlimited |
| uses | integer | The number of times the invite has been accepted |
| expiresAt | ?ISO8601 timestamp | When the invite expires, or null when it never expires |
| createdAt | ISO8601 timestamp | When the invite was created |
| channelId | ?snowflake | The channel the invite points at, or null for a guild-wide invite |
| channel | ?object | {id, name, type} of that channel, where type is a label such as "TEXT", or null |
Example¶
{
"id": "a1b2c3d4",
"code": "a1b2c3d4",
"serverId": "1489002177550843904",
"inviterId": "1501314428688998182",
"inviterName": "Example",
"inviter": { "id": "1501314428688998182", "name": "Example", "imageUrl": "" },
"maxUses": 25,
"uses": 3,
"expiresAt": "2026-08-05T11:22:19+00:00",
"createdAt": "2026-08-04T11:22:19+00:00",
"channelId": "1489002177550843905",
"channel": { "id": "1489002177550843905", "name": "general", "type": "TEXT" }
}
Custom invite URLs¶
A guild can have a permanent custom invite code (its vanity code). Get invite and Accept invite resolve it when no regular invite has that code. A custom invite URL never expires, has temporary false, and is not included in the invite lists.
Get invite¶
GET /invites/{invite_code}
Resolves one invite and returns an invite object. No authentication is required, and the read never consumes a use.
An expired invite does not resolve.
Response¶
| Status | Body | Condition |
|---|---|---|
| 200 | invite object | The invite resolved |
| 404 | error response | No invite or custom invite URL has this code, or the guild no longer exists (NOT_FOUND) |
Rate limit¶
100 requests per 10 seconds per client and invite code, on the invite:read bucket. The client is the session when an Authorization header is present, otherwise the IP address.
Example¶
Accept invite¶
POST /invites/{invite_code}
Accepts an invite and adds the authenticated account to its guild. User-only: a bot token is rejected with 403 ACCESS_DENIED. The caller needs no permission.
Response¶
On success the route returns 200 with a small status object:
When the account is already a member, it returns 200 with {"server_id": "...", "already_member": true} and no membership events are dispatched.
| Status | Body | Condition |
|---|---|---|
| 200 | status object | The account joined, or was already a member |
| 403 | error response | The caller is a bot (ACCESS_DENIED) |
| 403 | error response | The guild has paused invites (INVITES_DISABLED feature) or the caller is banned from the guild (FORBIDDEN) |
| 404 | error response | The code is unknown or expired (NOT_FOUND) |
Use limits
max_uses is stored and reported, but the accept route does not currently refuse an invite whose uses has reached max_uses. Use an expiry (max_age) or delete the invite to stop it.
Side effects¶
For a regular invite, uses is incremented as soon as the code resolves, before the paused, ban and already-member checks. A new admission records the invite code and inviter on the membership. Then:
- Guild Member Add is dispatched to the guild and the joining account's open sessions are connected to the guild.
- If the guild has a system channel and join messages are not hidden, a
USER_JOINsystem message (type7) is posted there and dispatched with Message Create. - If the account restricts DMs from new guilds, the guild is added to its restricted list.
Rate limit¶
10 requests per 10 seconds per user, on the invite:accept bucket (not partitioned by invite code).
Example¶
Delete invite¶
DELETE /invites/{invite_code}
Deletes an invite permanently. Returns 200 with {"message": "..."}.
The invite creator can delete their own invite while they are still a member of the guild; anyone else needs MANAGE_GUILD. Bot tokens are accepted.
Response¶
| Status | Body | Condition |
|---|---|---|
| 200 | {"message": string} |
The invite was deleted |
| 403 | error response | The caller is not the creator and lacks MANAGE_GUILD or is not a member (FORBIDDEN) |
| 404 | error response | No invite has this code (NOT_FOUND) |
Side effects¶
An INVITE_DELETE entry is written to the guild audit log, and an Invite Delete event carrying guild_id, code and channel_id is dispatched to the guild.
Rate limit¶
20 requests per 10 seconds per user and invite code, on the invite:delete bucket.
Create channel invite¶
POST /channels/{channel_id}/invites
Creates a new invite for a guild channel and returns 201 with an invite metadata object. Each call creates a new invite; existing invites are never reused.
Requires guild membership, VIEW_CHANNEL and CREATE_INSTANT_INVITE in that channel. Bot tokens are accepted.
JSON body¶
| Field | Type | Description |
|---|---|---|
| max_uses? | ?integer | Maximum number of uses; 0 or omitted means unlimited |
| max_age? | ?integer | Lifetime in seconds; 0 or omitted means the invite never expires |
| temporary? | ?boolean | The temporary flag stored on the invite (default false) |
Response¶
| Status | Body | Condition |
|---|---|---|
| 201 | invite metadata object | The invite was created |
| 403 | error response | The caller lacks VIEW_CHANNEL or CREATE_INSTANT_INVITE (FORBIDDEN) |
| 404 | error response | The channel does not exist, is not a guild channel, or the caller cannot see it (NOT_FOUND) |
Side effects¶
The new code is 8 random lowercase hexadecimal characters. An INVITE_CREATE entry is written to the guild audit log, and Invite Create is dispatched to the guild with the full invite (reference-style fields such as code, guild, channel, inviter, uses, max_uses, max_age, created_at, plus guild_id and channel_id).
Rate limit¶
20 requests per minute per user and channel, on the invite:create bucket.
Example¶
curl -X POST "https://tebhos.com/api/v1/channels/1489002177550843905/invites" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_age":86400,"max_uses":25}'
Create guild invite¶
POST /invites/server/{guild_id}
Creates a guild-wide invite that is not tied to a channel. Takes the same body as Create channel invite, plus an optional channel_id that scopes the invite to one channel of that guild. Without channel_id, it requires the CREATE_INSTANT_INVITE permission at guild level; with it, the permission is checked in that channel. Returns 201 with an invite metadata object.
List channel invites¶
GET /channels/{channel_id}/invites
Returns the active invites of one channel as an array of invite metadata objects, newest first. Requires access to the channel and MANAGE_CHANNELS in the guild. Expired invites are not included. Custom invite URLs are not included.
Rate limit¶
40 requests per 10 seconds per user and channel, on the invite:list bucket.
List guild invites¶
GET /guilds/{guild_id}/invites
Returns the active invites of one guild across all channels as an array of invite metadata objects, newest first. Requires MANAGE_GUILD. Bot tokens are accepted.
Expired invites are deleted when this list is read, so they never appear. The response is not paginated. Custom invite URLs are not included.
The same list is also available at GET /invites/server/{guild_id}.
Rate limit¶
40 requests per 10 seconds per user and guild, on the invite:list bucket.