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(content="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(content="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())

# Create DM
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(content="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(content="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.0

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.0
File Size Uploaded
drekord-2.0.0.tar.gz 27.6 kB Details

Built distribution (wheel)

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

Total release size: 57.2 kB

Release files / drekord-2.0.0.tar.gz

Download URL drekord-2.0.0.tar.gz
Size 27.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ef7c081575d6982de6fe74074f110bd5119007728b48be0f91f951ddc3230c1d
BLAKE2b-256 checksum
How to use checksums
9c81bf47de16cdcb649e3ffc6716c28f6b2aa1187574f64ace23fc3e57c908eb
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.0-py3-none-any.whl

Download URL drekord-2.0.0-py3-none-any.whl
Size 29.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
590c8ce3c1157c57564e9079abb4cf97719c79591a0dfd851909bcbabe0115dd
BLAKE2b-256 checksum
How to use checksums
47a29826d903a496ce643496d6edb43d53fa70da66e23b4546c77b721a2c4822
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

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

This release

2.0.0 This release

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