A lightweight wrapper for Discord's HTTP interactions and webhook events using py-cord and FastAPI.
- Overview
- Installation
- Quick Start
- Core Concepts
- Features
- Usage Examples
- Configuration
- Limitations
- Getting Help
- Development
- License
Pycord REST enables you to build Discord applications that respond to:
- Interactions via HTTP endpoints (slash commands, components, modals)
- Webhook events such as application authorization and entitlements
Built on:
- FastAPI - For handling HTTP requests
- py-cord - For Discord command builders and interaction handling
- uvicorn - ASGI server implementation
pip install pycord-rest-bot --prerelease=allow
Note
The package is currently in pre-release.
from pycord_rest import App
import discord
app = App()
@app.slash_command(name="ping", description="Responds with pong!")
async def ping(ctx):
await ctx.respond("Pong!")
if __name__ == "__main__":
app.run(
token="YOUR_BOT_TOKEN",
public_key="YOUR_PUBLIC_KEY", # From Discord Developer Portal
uvicorn_options={
"host": "0.0.0.0",
"port": 8000
}
)
Pycord REST creates an HTTP server that:
- Listens for Discord interaction requests and webhook events
- Verifies request signatures using your application's public key
- Routes events to appropriate handlers
- Returns responses back to Discord
Unlike traditional WebSocket-based Discord bots, HTTP-based applications:
- Only wake up when receiving interactions or webhook events
- Don't maintain a persistent connection to Discord's gateway
- Don't receive most real-time Discord events
- Create an application on the Discord Developer Portal
- Copy your public key to verify signatures
- Run the Pycord REST app
- Configure the endpoints:
- Interactions Endpoint URL - For slash commands and component interactions
(
https://example.com
) - Webhook URL - For receiving application events (e.g.,
https://example.com/webhook
)
Important
Don't forget to run your FastAPI server before setting up the application on Discord, or else Discord won't be able to verify the endpoints.
Respond to Discord interactions such as:
- Slash Commands - Create and respond to application commands
- UI Components - Buttons, select menus, and other interactive elements
- Modal Forms - Pop-up forms for gathering user input
- Autocomplete - Dynamic option suggestions as users type
Handle Discord webhook events such as:
- Application authorization - When your app is added to a guild or authorized by a user
- Entitlement creation - When a user subscribes to your app's premium features
Pycord REST is fully type-annotated and type-safe. It uses basedpyright
for type
checking.
Note
While Pycord REST itself is fully typed, the underlying py-cord library has limited type annotations, which may affect type checking in some areas.
Tip
For complete examples, check out the examples directory.
Commands use the familiar py-cord syntax:
@app.slash_command(name="hello", description="Say hello")
async def hello(ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.respond(f"Hello {user.mention}!")
@app.slash_command()
async def button(ctx):
view = discord.ui.View()
view.add_item(discord.ui.Button(label="Click me!", custom_id="my_button"))
await ctx.respond("Press the button!", view=view)
The possible events are:
on_application_authorized
- When your app is added to a guild or authorized by a useron_entitlement_create
- When a user subscribes to your app's premium features
Note
For application installation events, use on_application_authorized
instead of on_guild_join
.
@app.listen("on_application_authorized")
async def on_application_authorized(event: ApplicationAuthorizedEvent):
# Triggers when app is added to a guild OR when a user authorizes your app
print(f"Authorization received: Guild={event.guild}, User={event.user}")
Add your own FastAPI routes:
from fastapi import Request
@app.router.get("/custom")
async def custom_endpoint(request: Request):
return {"message": "This is a custom endpoint"}
app.run(
token="YOUR_BOT_TOKEN",
public_key="YOUR_PUBLIC_KEY",
uvicorn_options={
"host": "0.0.0.0", # Listen on all network interfaces
"port": 8000, # Port to listen on
"log_level": "info", # Uvicorn logging level
},
health=True # Enable /health endpoint for monitoring
)
- Stand-alone HTTP Interaction Bot - Commands and components only
- Webhook Event Handler Only - Process application events alongside a separate gateway bot
- Full HTTP Application - Handle both interactions and webhook events
Since Pycord REST doesn't use Discord's WebSocket gateway:
- No Cache - No local storage of guilds, channels, or users
- Limited API Methods - Functions that rely on cache won't work:
app.get_channel()
,app.get_guild()
,app.get_user()
- Presence updates
- Voice support
- Member tracking
- Limited Events - Only interaction-based and webhook events work
If you encounter issues or have questions about pycord-rest:
- GitHub Issues: Submit a bug report or feature request
- Discord Support:
- For py-cord related questions: Join the Pycord Official Server
- For pycord-rest specific help: Join the
Pycord Official Server and mention
@paillat
Tip
Before asking for help, check if your question is already answered in the examples directory or existing GitHub issues.
Use tunneling tools to expose your local development server:
-
ngrok:
# Install ngrok npm install -g ngrok # Expose your local server ngrok http 8000
-
Cloudflare Tunnel or localtunnel - Alternative tunneling options
These tools provide temporary URLs for testing without deploying to production.
- Fork the repository
- Create a feature branch
- Make your changes
- Run linter, formatter and type checker:
ruff check .
,ruff format .
,basedpyright .
- Submit a pull request
Development Tools:
- uv: For dependency management
- Ruff: For linting and formatting
- HashiCorp Copywrite: For managing license headers
- basedpyright: For type checking
Note
This is an early-stage project and may have unexpected behaviors or bugs. Please report any issues you encounter.
MIT License - Copyright (c) 2025 Paillat-dev
Made with ❤ by Paillat-dev