Skip to content

Relationships

A relationship describes a friendship, block, or pending friend request from the caller's perspective. Private notes belong to User notes.

All routes on this page are user-only. They require a user session token (Authorization: Bearer <token>). A valid Bot <token> credential is refused with 403 ACCESS_DENIED, and an invalid one with 401 UNAUTHORIZED.

Relationship records are directional

A friendship is a FRIEND record on both accounts. A pending request is OUTGOING_REQUEST on the sender and INCOMING_REQUEST on the recipient. A block exists only on the account that created it, so the blocked account holds no record for it.

Relationship object

A relationship record belongs to one account and names one other account. Every field describes the owning account's side, and every route on this page returns the caller's own record.

Structure

Field Type Description
id snowflake The ID of the related account. A relationship has no identifier of its own
type integer The relationship type
relation_type integer The same value as type, kept for older clients
user partial user object The related account, with two extra members described below
since ?ISO8601 timestamp The time the friendship was established. Only a FRIEND record carries a value; every other type has null
nickname ?string The caller-private nickname for the related account, or null when none is set
share_voice_activity boolean Whether the caller shares voice activity with the related account

The user object is the ordinary partial user with two additional members:

Field Type Description
name string The display name: the account's global_name when set, otherwise its username
image_url string The stored avatar URL, or an empty string when the account has none

share_voice_activity is false on every new record. It becomes true on the caller's FRIEND records only when the caller turns voice activity sharing on through Modify voice activity sharing, which rewrites all of the caller's friendships at once.

Not supported on TEBHOS

The record carries no friend_shares_voice_activity field. Read the other side's preference from their own presence instead.

Example

{
  "id": "1501314428688998182",
  "type": 1,
  "relation_type": 1,
  "user": {
    "id": "1501314428688998182",
    "username": "aria",
    "discriminator": "0000",
    "global_name": "Aria",
    "avatar": null,
    "avatar_color": null,
    "flags": 0,
    "name": "Aria",
    "image_url": ""
  },
  "since": "2026-01-14T09:31:00+00:00",
  "nickname": "climbing partner",
  "share_voice_activity": false
}

Relationship types

Value Name Description
1 FRIEND The two accounts are friends
2 BLOCKED The caller has blocked the related account
3 INCOMING_REQUEST The related account has sent the caller a friend request
4 OUTGOING_REQUEST The caller has sent the related account a friend request

Bulk ignore result object

A bulk ignore result reports how many incoming friend requests one call removed.

Structure

Field Type Description
ignored_count integer The number of incoming friend requests that were removed

Bulk ignore filters

Value Name Description
all All Matches every incoming friend request
new_accounts New accounts Matches an incoming friend request whose sender account is younger than max_account_age_seconds

new_accounts narrows the match only when max_account_age_seconds is also supplied. Without it, and for any value other than new_accounts, the call behaves as all.

Relationship limit

One account can hold at most 1000 relationship records in total, counting friendships, blocks, and pending requests in both directions. The limit is fixed and is not instance-configurable.

TEBHOS checks the caller and the target independently when a new friend request is created and when a pending request is accepted. A request fails when either account has reached the limit, with 400 MAX_FRIENDS. Blocking is not subject to the limit.

List relationships

GET /users/@me/relationships

Returns every relationship object the caller holds, covering friendships, blocks, and pending requests in both directions.

The operation is not paged, and the whole set comes back in one response. The order is not dependable. A connected client also receives the same set in the Gateway Ready payload.

Response

Status Body Condition
200 array of relationship objects Relationships were returned, possibly as an empty array

Rate limit

40 requests per 10 seconds for each authenticated user, on the user:relationships:list bucket.

Send friend request by username

POST /users/@me/relationships

Sends a friend request to the account identified by its username. Returns a relationship object on success.

TEBHOS usernames are unique, so the target is found by username alone and there is no discriminator field. The lookup is case-insensitive and ignores leading and trailing whitespace. Every rule after the lookup is the one described under Send friend request by user ID.

JSON body

Field Type Description
username string The username of the target account

Response

Status Body Condition
201 relationship object A pending request was created or already existed, or a pending incoming request was accepted
400 error response username is empty (BAD_REQUEST), or a rule listed under Send friend request by user ID rejects the request
404 error response No account has that username and the request returns NO_USERS_WITH_TEBHOSTAG_EXIST

Side effects

The side effects are those of Send friend request by user ID.

Rate limit

10 requests per 60 seconds for each authenticated user, on the user:friend_request:send bucket, shared with Send friend request by user ID.

Send friend request by user ID

POST /users/@me/relationships/{user_id}

Sends a friend request to the selected account. Returns a relationship object on success. The route reads no request body.

TEBHOS evaluates the request in this order:

  1. A user_id that is not an integer returns 400 BAD_REQUEST, and an ID that names no account returns 404 NOT_FOUND.
  2. The caller's own ID returns 400 CANNOT_SEND_FRIEND_REQUEST_TO_SELF.
  3. The caller's current record with the target decides the next step:
    • INCOMING_REQUEST: the pending request is accepted, exactly as Accept friend request or block user would, and the resulting FRIEND record is returned.
    • OUTGOING_REQUEST: the existing request is returned unchanged.
    • FRIEND: 400 ALREADY_FRIENDS.
    • BLOCKED (the caller blocked the target): 400 CANNOT_SEND_FRIEND_REQUEST_TO_BLOCKED_USER.
  4. A target that has blocked the caller returns 400 FRIEND_REQUEST_BLOCKED. The code is the same as the privacy refusal below, so the caller cannot tell that it is blocked.
  5. The target's friend request privacy setting (the friend source flags in user settings) is checked. A target that accepts requests only from friends of friends or from members of a shared guild rejects an unrelated caller with 400 FRIEND_REQUEST_BLOCKED.
  6. The relationship limit is checked for both accounts.

Steps 4 to 6 apply only to a genuinely new request. Accepting a pending incoming request (step 3) still checks the relationship limit, but not the privacy setting.

Path parameters

Field Type Description
user_id snowflake The ID of the target account

Response

Status Body Condition
201 relationship object A pending request was created or already existed, or a pending incoming request was accepted
400 error response The ID is malformed, the target is the caller, a relationship or privacy rule rejects the request, or the relationship limit is reached
404 error response The target account does not exist (NOT_FOUND), or a pending incoming request was withdrawn during acceptance (UNKNOWN_USER)

Side effects

A new request writes an OUTGOING_REQUEST record for the caller and an INCOMING_REQUEST record for the target, and emits Relationship Add to both accounts, each with its own record.

When the target had already sent the caller a request, both pending records are replaced with FRIEND records and Relationship Update reaches both accounts.

Returning an existing outgoing request writes nothing and emits nothing.

No path on this route opens a direct message channel.

Rate limit

10 requests per 60 seconds for each authenticated user, on the user:friend_request:send bucket, shared with Send friend request by username.

Accept friend request or block user

PUT /users/@me/relationships/{user_id}

Accepts a pending incoming friend request, or blocks the selected account when the body selects BLOCKED. Returns the caller's resulting relationship object.

The type member selects the operation

An omitted body, an omitted type, and type: 1 all select acceptance of a pending incoming request. type: 2 selects blocking. Any other value returns 400 BAD_REQUEST. Sending 1 does not create a friendship where no request exists.

Both operations return 400 BAD_REQUEST when user_id is malformed or is the caller's own ID, and 404 NOT_FOUND when it names no account.

Acceptance returns 404 UNKNOWN_USER when the caller holds no INCOMING_REQUEST record for the target, then applies the relationship limit to both accounts.

Blocking has no further admission rules. It is not subject to the relationship limit or to the target's privacy settings.

Path parameters

Field Type Description
user_id snowflake The ID of the target account

JSON body

The body can be omitted, in which case acceptance is selected.

Field Type Description
type? integer 1 to accept (default) or 2 to block. relation_type is accepted as an alias

Response

Status Body Condition
200 relationship object The friendship or the block was returned
400 error response The ID is malformed or is the caller, type is not 1 or 2, or the relationship limit is reached
404 error response The target account does not exist, or no pending incoming request exists

Side effects

Acceptance replaces the pending records on both accounts with FRIEND records, sets since to the current time, and emits Relationship Update to both accounts. It does not open a direct message channel; either side can open one with Create private channel.

Blocking deletes any existing record on both accounts (friendship or pending request in either direction) and writes a BLOCKED record for the caller only. Relationship Add reaches the caller with the block, and Relationship Remove reaches the target with the caller's ID. The Remove is sent even when the target held no record. Blocking an account that is already blocked rewrites the same record. Blocking never closes or deletes the pair's direct message channel.

Rate limit

20 requests per 10 seconds for each authenticated user, on the user:friend_request:accept bucket.

Remove relationship

DELETE /users/@me/relationships/{user_id}

Removes the caller's friendship, pending friend request in either direction, or block involving the selected account. Returns 204 with an empty body on success.

The route reads no request body. The caller's current record determines what is removed, so the same route unfriends, cancels or declines a request, and unblocks.

Path parameters

Field Type Description
user_id snowflake The ID of the related account

Response

Status Body Condition
204 empty The relationship was removed
400 error response user_id is malformed
404 error response The account does not exist, or the caller holds no relationship of any type with it (NOT_FOUND)

Side effects

Removing a friendship or a pending request in either direction removes both accounts' records and emits Relationship Remove to both, each carrying the other account's ID in id. Declining an incoming request therefore also removes the sender's OUTGOING_REQUEST record, and the sender is notified.

A block is stored on one account only, so removing one deletes the caller's record and emits Relationship Remove to the caller alone.

Rate limit

30 requests per 10 seconds for each authenticated user, on the user:relationship:delete bucket.

Modify relationship nickname

PATCH /users/@me/relationships/{user_id}

Sets or clears the caller's private nickname for a friend. Returns the updated relationship object. Emits a Relationship Update Gateway event to the caller.

Only a FRIEND record accepts a nickname. Every other relationship state returns 404 NOT_FOUND.

The nickname is private to the caller

TEBHOS writes it only to the caller's record. The friend never reads it in a response and never receives it in a Dispatch.

Path parameters

Field Type Description
user_id snowflake The ID of the friend

JSON body

Field Type Description
nickname? ?string The nickname to store, or null (or an omitted member) to clear it

The value is stored as sent. The server does not trim it, and a literal empty string is stored as an empty string rather than cleared.

Response

Status Body Condition
200 relationship object The updated relationship was returned
400 error response user_id is malformed or the body is not a JSON object
404 error response The account does not exist or no FRIEND record exists with it

Side effects

The record changes only for the caller, and share_voice_activity keeps its stored value. A stored since value is preserved, and a record that has none is stamped with the current time. Relationship Update reaches the caller for every accepted request, including one that submits the value already stored.

Rate limit

30 requests per 10 seconds for each authenticated user, on the user:relationship:update bucket.

Ignore pending requests in bulk

POST /users/@me/relationships/bulk-ignore

Removes matching incoming friend requests. Returns a bulk ignore result object on success.

Matching applies only to the caller's INCOMING_REQUEST records. TEBHOS derives a sender's account age from the timestamp embedded in its snowflake and compares it against max_account_age_seconds as an exclusive upper bound, so a sender exactly that old is not matched. One call removes every matching request.

An unbounded new_accounts filter removes everything

The age comparison applies only when max_account_age_seconds is supplied. Selecting new_accounts without it removes every incoming friend request, exactly as all does.

JSON body

The body can be omitted, in which case the all filter applies.

Field Type Description
filter? string The bulk ignore filter to apply (default all)
max_account_age_seconds? integer The exclusive maximum sender account age in seconds, read only by the new_accounts filter. A value of 0 or below matches no sender

Response

Status Body Condition
200 bulk ignore result object Matching requests were removed, possibly none

Side effects

Each matched request removes the caller's INCOMING_REQUEST record and the sender's OUTGOING_REQUEST record, and emits Relationship Remove to the caller and to the sender. A call that matches nothing changes nothing.

A call that fails partway can remove some incoming friend requests and return no count. Call List relationships again to read what remains.

Rate limit

5 requests per 60 seconds for each authenticated user, on the relationship:bulk_ignore bucket.

Gateway events

Every relationship Dispatch goes only to the sessions of the account it names:

Event Payload
RELATIONSHIP_ADD The recipient's relationship object
RELATIONSHIP_UPDATE The recipient's updated relationship object
RELATIONSHIP_REMOVE An object whose id is the related account's ID

See Gateway events for the envelope.