Skip to main content

Drekord Discord API Wrapper

A lightweight, async Discord REST API wrapper for Python.

Drekord is NOT a bot framework (like discord.py). It is a pure REST API client designed to be integrated into any async application that needs to interact with the Discord API, without maintaining a persistent WebSocket connection.

Features

  • Pure REST: No WebSocket gateway; just API calls x)
  • Fully async: Built on aiohttp for clean async/await usage
  • Object-Oriented: Call methods directly on channels, messages, users, guilds, etc.
  • discord.py-inspired: Familiar API if you've used discord.py before
  • Rate-limit awareness: Automatic retry on rate limits and transient errors

Installation

pip install drekord

Or from source:

git clone https://github.com/drek124/drekord.git
cd drekord
pip install -e .

Quick Start

import asyncio
import drekord


async def main():
    async with drekord.Client(token="YOUR_BOT_TOKEN") as client:
        # Get the current bot user
        me = await client.me()
        print(f"Logged in as {me.username}")

        # Fetch a channel and send a message
        channel = await client.fetch_channel(CHANNEL_ID)
        msg = await channel.send("Hello from Drekord! 🎉")
        print(f"Sent message {msg.id}")

        # Read the last 10 messages
        messages = await channel.fetch_messages(limit=10)
        for m in messages:
            print(f"{m.author.username}: {m.content}")


asyncio.run(main())

API Overview

Client Methods

Top-level fetch_* methods on the client:

await client.me()                              # Current bot user
await client.fetch_user(user_id)               # Any user
await client.fetch_channel(channel_id)         # Any channel
await client.fetch_message(channel_id, msg_id) # A specific message
await client.fetch_guilds()                    # List bot's guilds
await client.fetch_guild(guild_id)             # A specific guild
await client.fetch_member(guild_id, user_id)   # A guild member
await client.fetch_webhook(webhook_id)         # A webhook
await client.fetch_webhooks(channel_id)        # Webhooks in a channel

Channels

channel = await client.fetch_channel(channel_id)

# Send messages
msg = await channel.send("Hello!", tts=False)
msg = await channel.send(embeds=[embed])
msg = await channel.send(view=layout_view)  # Components V2

# Read messages
messages = await channel.fetch_messages(limit=50)
message = await channel.fetch_message(message_id)

# Edit the channel
channel = await channel.edit(name="renamed", topic="New topic")

# Delete the channel
await channel.delete()

# Typing indicator
await channel.typing()

# Invites
invites = await channel.fetch_invites()

Messages

message = await channel.fetch_message(msg_id)

# Edit
await message.edit(content="Edited!")

# Delete
await message.delete(reason="Cleanup requested")

# Pin/Unpin
await message.pin()
await message.unpin()

# Reactions
await message.add_reaction("👍")
await message.remove_reaction("👍")

# Crosspost (announcements)
await message.crosspost()

Users

user = await client.fetch_user(user_id)

# Properties
print(user.username)
print(user.display_name)  # global_name or username
print(user.avatar_url())

# Send a DM (auto-creates DM channel)
await user.send("Hello!")
await user.send("Check this out!", embeds=[embed])

# Or create the DM channel explicitly
dm_channel = await user.create_dm()

# Re-fetch
user = await user.fetch()

Guilds

guild = await client.fetch_guild(guild_id)

# Properties
print(guild.name)

# Fetch sub-resources
channels = await guild.fetch_channels()
members = await guild.fetch_members(limit=100)
roles = await guild.fetch_roles()
emojis = await guild.fetch_emojis()
bans = await guild.fetch_bans()
audit_logs = await guild.fetch_audit_logs(limit=50)

# Create
new_channel = await guild.create_channel({"name": "new-channel", "type": 0})
new_role = await guild.create_role({"name": "Moderator", "color": 0xFF0000})

# Edit
guild = await guild.edit({"name": "New Name"})

# Leave / Delete
await guild.leave()
await guild.delete()

Members

member = await client.fetch_member(guild_id, user_id)

# Properties
print(member.display_name)
print(member.roles)
print(member.joined_at)

# Actions
await member.kick(reason="Rule violation")
await member.ban(reason="Spam", delete_message_days=7)
await member.edit(nick="New Nick", roles=[role_id1, role_id2])

Webhooks

webhook = await client.fetch_webhook(webhook_id)

# Execute (send)
await webhook.execute("Hello!", username="Bot")
await webhook.execute(embeds=[embed], wait=True)

# Edit
await webhook.edit({"name": "New Name"})

# Delete
await webhook.delete()

Embeds

embed = drekord.Embed(
    title="Hello",
    description="World",
    color=0x5865F2,
)
embed.set_thumbnail(url="https://example.com/thumb.png")
embed.add_field(name="Field 1", value="Value 1", inline=True)
embed.set_footer(text="Footer text")

await channel.send(embeds=[embed])

Components V2

from drekord.ui import (
    LayoutView, Container, TextDisplay, Separator,
    ActionRow, Button, Section, Thumbnail,
)

view = LayoutView()
view.add_item(Container(
    TextDisplay("## Hello World"),
    Separator(),
    ActionRow(
        Button(label="Click Me", style=1, custom_id="btn_1"),
    ),
    accent_color="#5865F2",
))

await channel.send(view=view)

Raw Requests (Escape Hatch)

For endpoints not yet covered:

data = await client.request("GET", "/gateway")
data = await client.request("POST", "/channels/123/threads", json={"name": "Thread"})

Error Handling

Drekord raises typed exceptions for all error cases:

import drekord

try:
    msg = await channel.send("Hello!")
except drekord.ForbiddenError:
    print("I don't have permission to send messages here!")
except drekord.NotFoundError:
    print("Channel not found!")
except drekord.RateLimitedError as e:
    print(f"Rate limited! Retry after {e.retry_after}s")
except drekord.HTTPError as e:
    print(f"HTTP error {e.status_code}: {e}")

Exception Hierarchy

DrekordError
  └── HTTPError
        ├── BadRequestError      (400)
        ├── UnauthorizedError    (401)
        ├── ForbiddenError       (403)
        ├── NotFoundError        (404)
        ├── RateLimitedError     (429)
        └── DiscordServerError   (5xx)

Models

All API responses are returned as model objects with typed properties:

user = await client.fetch_user(user_id)
print(user.id)            # int
print(user.username)      # str
print(user.display_name)  # str (global_name or username)
print(user.bot)           # bool
print(user.avatar_url())  # str | None

channel = await client.fetch_channel(channel_id)
print(channel.id)         # int
print(channel.name)       # str | None
print(channel.type_name)  # str ("text", "voice", etc.)

message = await channel.fetch_message(msg_id)
print(message.content)    # str
print(message.author)     # User | None
print(message.embeds)     # list[Embed]

License

MIT

Release files for drekord 2.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for drekord 2.0.3
File Size Uploaded
drekord-2.0.3.tar.gz 27.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for drekord 2.0.3
File Interpreter ABI Platform
drekord-2.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 57.8 kB

Release files / drekord-2.0.3.tar.gz

Download URL drekord-2.0.3.tar.gz
Size 27.9 kB
Tags Source
SHA-256 checksum
How to use checksums
43b025eb1d7f12b1ef50a9033d5bd349402639bd61cac50976b142c3b8b344de
BLAKE2b-256 checksum
How to use checksums
8f903d7f802e75c968a010a143ec4d5138c200531c4ad4b71a409296e19c2cc3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / drekord-2.0.3-py3-none-any.whl

Download URL drekord-2.0.3-py3-none-any.whl
Size 29.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f1cedbc078b88ad988d3d3a56c184ea7408ba98a8223626422780e92bc108df2
BLAKE2b-256 checksum
How to use checksums
e0f89fce614e2756a5f1a9660d3f19da2ada8204635ac07741a3ee575c8cc90b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

2.0.3 This release

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page