> ## Documentation Index
> Fetch the complete documentation index at: https://docs.guilt.icu/llms.txt
> Use this file to discover all available pages before exploring further.

# User and DM HTTP Methods for the alterself REST API Guide

> Fetch user profiles, edit your own account, open DMs, manage relationships, and make raw API requests using alterself's bot.http user methods.

User operations in alterself range from looking up another account's public profile to modifying your own avatar and display name. All methods live on `bot.http`, the library's shared HTTP client, and are **async**, so you must `await` every call. The client automatically applies rate-limit management and realistic browser headers on every request, keeping your traffic consistent with a normal Discord session.

***

## User Methods

### fetch\_me

Fetch the full User object for your own account.

```python theme={null}
me = await bot.http.fetch_me()
```

**Returns:** A `dict` representing your own [User object](https://discord.com/developers/docs/resources/user#user-object), including your `id`, `username`, `global_name`, `discriminator`, `avatar`, and account flags.

***

### fetch\_user

Retrieve publicly available information about any Discord user by their ID.

```python theme={null}
user = await bot.http.fetch_user(user_id)
```

<ParamField path="user_id" type="int | str" required>
  The ID of the user to look up.
</ParamField>

**Returns:** A partial User object `dict` containing publicly visible fields only. You will not receive email, phone, or other private fields for other users.

***

### fetch\_profile

Retrieve a user's full public profile, including mutual guilds, mutual friends, connected accounts, and premium (Nitro) status. Optionally scope the lookup to a specific guild for server-specific details like the member's nickname and roles.

```python theme={null}
profile = await bot.http.fetch_profile(user_id)
profile = await bot.http.fetch_profile(user_id, guild_id=guild_id)
```

<ParamField path="user_id" type="int | str" required>
  The ID of the user whose profile you want to fetch.
</ParamField>

<ParamField path="guild_id" type="int | str">
  When provided, the response includes guild-specific member data such as the user's server nickname, roles, and join date for that guild.
</ParamField>

**Returns:** A `dict` containing the user's `user` object, `connected_accounts`, `mutual_guilds`, `mutual_friends`, and premium information.

<Note>
  Profile fetches are rate-limited more aggressively than standard user lookups. Avoid fetching large numbers of profiles in rapid succession.
</Note>

***

### edit\_me

Modify your own account's username, display name, avatar, or other settings.

```python theme={null}
me = await bot.http.edit_me(
    username    = "newname",
    global_name = "Display Name",
    # avatar: pass base64-encoded "data:image/png;base64,..." string
)
```

<ParamField path="username" type="str">
  Your new username. Must be unique across Discord and between 2 and 32 characters. Changing your username may alter your discriminator.
</ParamField>

<ParamField path="global_name" type="str">
  Your new display name (shown in place of your username in most UI surfaces). Between 1 and 32 characters.
</ParamField>

<ParamField path="avatar" type="str">
  A base64-encoded image string in the format `"data:image/png;base64,<data>"`. JPEG and GIF are also accepted. Pass `null` to remove your avatar.
</ParamField>

<ParamField path="banner" type="str">
  A base64-encoded image string for your profile banner. Requires an active Nitro subscription.
</ParamField>

**Returns:** The updated User object as a `dict`.

<Warning>
  Discord rate-limits username changes strictly: you can only change your username a limited number of times. Rapid automated changes can trigger account verification prompts.
</Warning>

<Tip>
  To load an avatar from a file, read it and encode it yourself before passing it to `edit_me`:

  ```python theme={null}
  import base64

  with open("avatar.png", "rb") as f:
      b64 = base64.b64encode(f.read()).decode()

  await bot.http.edit_me(avatar=f"data:image/png;base64,{b64}")
  ```
</Tip>

***

### fetch\_me\_guilds

Retrieve a list of all guilds your account is currently a member of.

```python theme={null}
guilds = await bot.http.fetch_me_guilds()
```

**Returns:** A `list[dict]` of partial Guild objects. Each entry includes the guild's `id`, `name`, `icon`, `owner` flag, and your permission bitfield for that guild.

***

### fetch\_connections

Retrieve the list of third-party accounts (Twitch, YouTube, GitHub, Steam, etc.) connected to your Discord account.

```python theme={null}
conns = await bot.http.fetch_connections()
```

**Returns:** A `list[dict]`, each representing a connected account with fields like `type`, `id`, `name`, and `verified`.

***

## DMs and Relationships

### open\_dm

Open (or re-open) a Direct Message channel with another user. If a DM channel already exists, Discord returns the existing one.

```python theme={null}
dm = await bot.http.open_dm(user_id)
```

<ParamField path="user_id" type="int | str" required>
  The ID of the user you want to open a DM with.
</ParamField>

**Returns:** A Channel object `dict` of type `1` (DM). Use `dm["id"]` as the `channel_id` for subsequent `send_message` calls.

***

### fetch\_relationships

Retrieve all relationships on your account: friends, pending incoming/outgoing friend requests, and blocked users.

```python theme={null}
rels = await bot.http.fetch_relationships()
```

**Returns:** A `list[dict]`, each containing a `type` integer and a partial `user` object.

| `type` | Meaning |
| - | - |
| `1` | Friend |
| `2` | Blocked |
| `3` | Incoming friend request |
| `4` | Outgoing friend request |

***

### add\_friend

Send a friend request to another user.

```python theme={null}
await bot.http.add_friend(user_id)
```

<ParamField path="user_id" type="int | str" required>
  The ID of the user to send a friend request to.
</ParamField>

**Returns:** `None` on success.

***

### remove\_friend

Unfriend a user or cancel a pending friend request.

```python theme={null}
await bot.http.remove_friend(user_id)
```

<ParamField path="user_id" type="int | str" required>
  The ID of the user to remove from your friends list.
</ParamField>

**Returns:** `None` on success.

***

### block\_user

Block a user. Blocked users cannot send you friend requests or DMs.

```python theme={null}
await bot.http.block_user(user_id)
```

<ParamField path="user_id" type="int | str" required>
  The ID of the user to block.
</ParamField>

**Returns:** `None` on success.

***

## Raw Requests

When you need to call a Discord endpoint that alterself doesn't yet wrap with a dedicated method, you can drop down to the raw `request` method. Construct an `Endpoint` object with the HTTP verb and path, then pass it directly to `bot.http.request`. All rate-limit management, header spoofing, and retry logic still applies, so you get the full benefit of the client without being limited to the built-in helpers.

```python theme={null}
from alterself.http.route import Endpoint

ep   = Endpoint("GET", "/users/@me/affinities/guilds")
data = await bot.http.request(ep)
```

<ParamField path="endpoint" type="Endpoint" required>
  An `Endpoint` instance created via `Endpoint(method, path)` where `method` is an HTTP verb string (`"GET"`, `"POST"`, `"PATCH"`, `"DELETE"`, etc.) and `path` is the Discord API path starting with `/`.
</ParamField>

<ParamField path="json" type="dict">
  A JSON-serialisable dict to send as the request body. Used for `POST`, `PATCH`, and `PUT` requests.
</ParamField>

<ParamField path="params" type="dict">
  Query string parameters to append to the URL.
</ParamField>

**Returns:** The parsed JSON response as a `dict` or `list`, depending on the endpoint. Returns `None` for endpoints that respond with `204 No Content`.

<Tip>
  Check the [Discord API documentation](https://discord.com/developers/docs/reference) for a full list of available endpoints and their required fields when using raw requests.
</Tip>

***

## Rate Limits

alterself's HTTP client manages Discord's complex per-route rate-limit buckets automatically. When a bucket is exhausted, the client sleeps until the reset time and retries. Your `await` simply takes longer rather than raising an exception. You never need to write backoff logic yourself.

You can inspect the current state of the rate-limit manager at any time:

```python theme={null}
print(bot.http._rl.stats())
# {'buckets': 12, 'global_until': 0.0, 'exhausted': []}
```

| Key | Type | Description |
| - | - | - |
| `buckets` | `int` | Number of distinct rate-limit buckets currently tracked by the client. |
| `global_until` | `float` | Unix timestamp at which a global rate-limit clears. `0.0` means no active global limit. |
| `exhausted` | `list[str]` | List of bucket identifiers currently waiting for their reset window. Empty is healthy. |

<Note>
  `_rl` is an internal attribute. Its interface may change between alterself releases. Use `stats()` for observability only. Do not modify the rate-limit state directly.
</Note>
