Back to blog

PawSharp: A Fresh, Modular .NET 8 Discord API Wrapper for Modern Bot Development

March 8, 2026 16 min read
dotnetdotnet8discord-botcsharpnugetapi-wrappergatewaye2ee

Introduction

Building Discord bots in .NET has traditionally meant choosing from a small set of long-standing libraries. Many of these started years ago and have grown into complex frameworks with layers of abstractions, backward compatibility constraints, and design decisions that made perfect sense back then but feel cumbersome today.

PawSharp takes a clean-sheet approach. Designed specifically for .NET 8, it's a modular, fully opt-in Discord API wrapper that covers the entire API surface—REST, Gateway, voice, interactions—while letting you include only the pieces your project actually needs. Whether you're throwing together a quick personal bot or engineering a sharded, high-throughput production system, PawSharp puts control back in your hands without unnecessary baggage.

As of early 2026, PawSharp sits at version 0.10.0-alpha.3, targeting Discord API v10. The public surface is still evolving (as alphas do), but the core architecture has proven stable enough for real-world bots. Developers are already using it in production-like settings, and the pace of iteration is brisk.

What Exactly Is PawSharp?

At its heart, PawSharp is a set of NuGet packages that provide a clean, strongly-typed interface to the Discord API. It handles:

  • WebSocket Gateway management—authentication, heartbeats, resuming sessions, sharding, and event dispatching
  • Roughly 140 REST endpoints covering messages and channels through to guilds, AutoMod rules, polls, and stage instances
  • An automatic in-memory entity cache kept fresh via gateway events
  • Per-route rate-limit bucket tracking with built-in 429 retry logic
  • Slash commands, message components (buttons, menus), and modals through a dedicated interaction router
  • Traditional prefix-based text commands via attributes and modules
  • Voice connections, including a full from-scratch implementation of Discord's DAVE end-to-end encryption (based on RFC 9420 MLS) using only .NET 8's native cryptography APIs—no external dependencies

The real win is the modular packaging. You install exactly what you need:

# Full-featured client (recommended for most bots)
dotnet add package PawSharp.Client

# Or pick and choose
dotnet add package PawSharp.API          # REST only
dotnet add package PawSharp.Gateway      # Gateway + events
dotnet add package PawSharp.Commands     # Prefix commands
dotnet add package PawSharp.Interactions # Slash commands & components
dotnet add package PawSharp.Interactivity# Reactions, polls, pagination helpers
dotnet add package PawSharp.Voice        # Voice + DAVE encryption

This keeps your dependency graph lean and your build artifacts small.

Getting Started: Hello World in ~40 Lines

PawSharp's fluent builder makes bootstrapping painless—no heavy DI setup required if you don't want it:

var client = new PawSharpClientBuilder()
    .WithToken("YOUR_BOT_TOKEN_HERE")
    .WithIntents(GatewayIntents.AllNonPrivileged | GatewayIntents.MessageContent)
    .WithPresence("Just getting started", status: "online")
    .UseConsoleLogging()
    .Build();

client.OnMessageCreated(async msg =>
{
    if (msg.Author?.IsBot == true) return;
    if (msg.Content?.Trim().ToLower() == "!ping")
    {
        await client.Rest.CreateMessageAsync(msg.ChannelId, new() { Content = "Pong!" });
    }
});

await client.ConnectAsync();
await Task.Delay(Timeout.Infinite);

That's genuinely all it takes. The builder assembles the REST client, gateway listener, cache, and interaction handler under a single DiscordClient object. No manual WebSocket plumbing, no heartbeat timers to manage.

Core Features at a Glance

REST API: Comprehensive and Strongly Typed

The PawSharp.API package gives you IDiscordRestClient with fully typed models for nearly the entire v10 REST surface. Key areas include messages (create/edit/delete/react/bulk), channels (CRUD + overwrites/invites/pins), guilds (members/roles/emojis/stickers/events), threads, webhooks, AutoMod rules, polls, and stage instances.

Enums replace magic numbers everywhere—AutoModerationTriggerType, StageInstancePrivacyLevel, and so on—so the compiler catches typos early.

Rate Limiting: Hands-Off and Reliable

Rate limits are handled transparently by AdvancedRateLimiter. It tracks per-route buckets, respects the global cap, and retries 429s automatically. You write normal code:

await client.Rest.CreateMessageAsync(channelId, new() { Content = "Sending this safely" });

Only if retries are exhausted do you get a RateLimitException.

Gateway: Full Coverage with Auto-Reconnect

PawSharp.Gateway owns the WebSocket lifecycle: IDENTIFY/RESUME, heartbeats (with LastHeartbeatLatency tracking), sharding via ShardManager, and over 40 event types dispatched cleanly.

Convenience events make subscription easy:

client.OnGuildMemberAdded(async member =>
{
    await client.Rest.CreateMessageAsync(welcomeChannelId, new()
    {
        Content = $"Welcome aboard, <@{member.User?.Id}>!"
    });
});

Recent additions in 0.10.0-alpha.3 include voice state updates, audit logs, scheduled event RSVPs, and more.

Caching: Simple and Extensible

Entities—guilds, channels, members, and more—are cached automatically via gateway events. Fetch them sync or async:

var guild = await client.Cache.GetGuildAsync(guildId);

Out-of-the-box providers include a zero-overhead MemoryCacheProvider and an async RedisCacheProvider (already implemented and tested in the repo, though not yet published as a separate NuGet package).

Interactions: Modern Components Done Right

Slash commands, buttons, select menus, and modals are routed automatically:

client.Interactions.RegisterCommand("greet", async interaction =>
{
    var name = interaction.GetOptionValue<string>("name") ?? "world";
    await client.Interactions.RespondAsync(interaction.Id, interaction.Token,
        new InteractionResponseBuilder()
            .WithContent($"Hello, {name}!")
            .AsEphemeral()
            .Build());
});

Fluent builders enforce Discord constraints at compile time where possible—for example, a maximum of 5 components per action row.

Prefix Commands: Familiar and Flexible

Classic !command style uses attributes:

var commands = client.UseCommands("!");

public class FunCommands : BaseCommandModule
{
    [Command("ping")]
    public async Task Ping(CommandContext ctx)
        => await ctx.RespondAsync("Pong!");
}

commands.RegisterModule(new FunCommands());

Exceptions bubble up via CommandErrored for clean handling.

Voice + Native DAVE Encryption

Voice connections are straightforward, but the standout feature is the built-in DAVE (MLS-based E2EE) implementation—entirely in .NET 8 cryptography primitives (X25519, Ed25519, HPKE, and so on), with zero external crypto libraries.

var voice = client.UseVoice();
var conn = await voice.ConnectAsync(voiceChannelId);
await conn.PlayAudioAsync(rawOpusData);  // Opus encode/decode pipeline is in progress
await conn.DisconnectAsync();

Note: Opus codec encode/decode is not yet implemented—voice works for connection and handshake but not audio send/receive.

Dependency Injection Support

Everything is interface-based and DI-friendly:

services.AddPawSharpWithMemoryCache(options =>
{
    options.Token = Environment.GetEnvironmentVariable("DISCORD_TOKEN")!;
});

Structured Error Handling

PawSharp avoids generic exceptions. The three you'll encounter are:

  • ValidationException — caught before the request leaves your code
  • RateLimitException — thrown after retries are exhausted
  • DiscordApiException — carries Discord's specific error code and message
try
{
    await client.Rest.CreateMessageAsync(...);
}
catch (DiscordApiException ex)
{
    // Handle known Discord error codes, e.g., 50035
}

Current Limitations (Alpha Transparency)

PawSharp is alpha software. Expect breaking changes before 1.0. Known gaps include:

  • Opus audio codec (send/receive not yet wired up)
  • Automatic command module discovery via reflection
  • Attribute-based slash command bulk registration
  • Published Redis cache package

The CHANGELOG tracks changes closely—read it before upgrading.

Why Consider PawSharp?

Compared to established options like Discord.Net or DSharpPlus:

  • Truly modular packages — smaller dependencies, cleaner builds
  • Native .NET 8 design — modern idioms, no legacy cruft
  • Unique native DAVE E2EE — meaningful for privacy-sensitive voice use cases
  • Strong typing + fluent validation — fewer runtime surprises
  • Transparent rate limiting + DI-first — fits cleanly into ASP.NET Core or generic hosts

Trade-offs exist: a smaller community, a less battle-tested ecosystem, and an API that is still evolving. If your bot needs music playback right now, wait for Opus completion. For everything else—especially new projects in 2026—PawSharp feels refreshingly contemporary.

Project Structure (For Curious Contributors)

src/
  PawSharp.Core          entities, enums, builders, exceptions
  PawSharp.API           REST + rate limiter
  PawSharp.Gateway       WebSocket + sharding
  PawSharp.Cache         cache providers
  PawSharp.Client        unified DiscordClient
  PawSharp.Commands      prefix command system
  PawSharp.Interactions  slash + components
  PawSharp.Interactivity helpers (reactions, polls...)
  PawSharp.Voice         voice + DAVE
tests/                   80+ unit/integration tests
examples/                sample bots
docs/                    developer guides

MIT licensed, with contributing guidelines and a code of conduct in the repository root.

Wrapping Up

PawSharp delivers a surprisingly complete Discord API experience in a lightweight, modern .NET 8 package. Its modular design, strong typing, native DAVE implementation, and transparent internals make it a compelling choice for developers who want to escape legacy abstractions.

Give it a try on your next bot project.