reysa / discord-api
Full-coverage Discord HTTP API client for Laravel -- call Discord's REST API through simple static PHP methods instead of raw HTTP calls.
Requires
- php: >=8.2
- illuminate/support: ^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Call Discord's HTTP API from Laravel through simple static method calls instead of hand-rolling
Guzzle/Http:: requests, headers, and URLs yourself:
DAPI::sendMessageToChannel($channelId, ['content' => 'Hello from Laravel!']); DAPI::giveRole($userId, [$roleId]); DAPI::getGuildChannels($guildId);
v2 covers essentially every endpoint Discord officially documents for bots — Guilds, Channels, Messages, Users, Webhooks, Emojis, Stickers, Invites, Application Commands & Interactions, Audit Log, Auto Moderation, Scheduled Events, Stage Instances, Soundboard, Polls, Voice, Monetization, and OAuth2. Not covered: the Gateway (WebSocket real-time events) and the Discord Social SDK/Lobby endpoints — different protocol/product, outside the scope of an HTTP client wrapper.
Official Discord API documentation: https://discord.com/developers/docs/intro
Table of contents
- What's new in v2
- Requirements
- Installation
- Configuration
- Quick usage example
- Full API coverage
- Browsable docs & live testing (Swagger)
- API reference (core helpers)
- Versioning & roadmap
- Contributing
- License
What's new in v2
- Full endpoint coverage — ~218 methods across 21 resource categories (up from 15 helpers in v1), generated directly from Discord's official docs source so paths/params match exactly. See Full API coverage for the breakdown.
- Interactive documentation — a Swagger UI you can run locally that documents every method as the actual PHP call you write, with real example payloads, and lets you fire live test requests against your own bot. See Browsable docs & live testing.
- Docker test harness —
docker compose up, no local PHP/Composer setup needed to try the package against a real Discord server. - Breaking change:
giveRole()/removeRole()now returnResponse[]keyed by role ID instead of a singleResponse— see their reference entries for why. - Every v1 method still works exactly as it did (same names, same arguments) except that one documented change.
Requirements
Check composer.json for exact constraints, but the package is designed to work with:
- PHP:
>= 8.2 - Laravel:
7.xup to13.x(viailluminate/support^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0). Onlyilluminate/support(config, HTTP client, facades) is required — no framework internals this package depends on have changed across that range, so newer Laravel majors will typically keep working without a package update; the constraint just gets widened once released.
Installation
Install the package via Composer:
composer require reysa/discord-api
Laravel’s package auto-discovery will automatically register the service provider and facade.
You can also find the package on Packagist:
https://packagist.org/packages/reysa/discord-api
Configuration
Publish the config file:
php artisan vendor:publish --tag=discord-api-config
This will create config/discord-api.php in your Laravel application:
<?php return [ 'bot_token' => env('DISCORD_BOT_TOKEN'), 'guild_id' => env('GUILD_ID'), ];
Then set the values in your .env file:
DISCORD_BOT_TOKEN=your_bot_token_here GUILD_ID=your_guild_id_here
Quick Usage Example
The package ships with a facade alias DAPI.
<?php use Reysa\DiscordAPI\Facades\DAPI; use Illuminate\Support\Facades\Route; Route::get('/test-discord', function () { DAPI::sendMessageToChannel( '123456789012345678', ['content' => 'Hello from Reysa Discord API!'] ); return 'Message sent (if token and channel are correct).'; });
Note: For methods like
sendMessageToChannelandsendEmbedMessageToUser,
the second argument is the raw payload array that Discord accepts
(for example:['content' => '...'],['embeds' => [...]], etc).
In v1 this payload is passed directly to the HTTP request body without additional validation.
Full API coverage
~218 methods total. Request bodies for POST/PUT/PATCH calls are passed through to Discord as-is (no field validation) — see the linked official docs page per category for the exact payload shape, or browse it interactively in Swagger (below).
| Category | Methods | Source file | Official docs |
|---|---|---|---|
| Core helpers (v1) | 14 | src/DAPI.php |
— |
| Guilds (settings, members, roles, bans, widgets, onboarding) | 40 | Concerns/InteractsWithGuilds.php |
Guild |
| Channels (CRUD, permissions, threads, pins, invites) | 24 | Concerns/InteractsWithChannels.php |
Channel |
| Application Commands (slash commands) | 16 | Concerns/InteractsWithApplicationCommands.php |
Application Commands |
| Webhooks | 15 | Concerns/InteractsWithWebhooks.php |
Webhook |
| Messages (send, edit, delete, react, bulk-delete, pins) | 14 | Concerns/InteractsWithMessages.php |
Message |
| Users | 12 | Concerns/InteractsWithUsers.php |
User |
| Emojis | 10 | Concerns/InteractsWithEmojis.php |
Emoji |
| Monetization (SKUs, entitlements, subscriptions) | 8 | Concerns/InteractsWithMonetization.php |
SKU |
| Interactions (responding/following up) | 8 | Concerns/InteractsWithInteractions.php |
Receiving & Responding |
| Stickers | 8 | Concerns/InteractsWithStickers.php |
Sticker |
| Soundboard | 7 | Concerns/InteractsWithSoundboard.php |
Soundboard |
| Guild Scheduled Events | 6 | Concerns/InteractsWithScheduledEvents.php |
Guild Scheduled Event |
| Guild Templates | 6 | Concerns/InteractsWithGuildTemplates.php |
Guild Template |
| Auto Moderation | 5 | Concerns/InteractsWithAutoModeration.php |
Auto Moderation |
| Voice | 5 | Concerns/InteractsWithVoice.php |
Voice |
| Invites | 4 | Concerns/InteractsWithInvites.php |
Invite |
| Stage Instances | 4 | Concerns/InteractsWithStageInstances.php |
Stage Instance |
| Applications | 3 | Concerns/InteractsWithApplications.php |
Application |
| OAuth2 (code exchange, refresh, revoke, authorization URL) | 6 | Concerns/InteractsWithOAuth2.php |
OAuth2 |
| Polls | 2 | Concerns/InteractsWithPolls.php |
Poll |
| Audit Log | 1 | Concerns/InteractsWithAuditLog.php |
Audit Log |
Method names mirror Discord's own endpoint titles (e.g. "Get Guild Channels" →
getGuildChannels()), so if you know the Discord docs, you already know the method name.
Browsable docs & live testing (Swagger)
Every method above is also documented interactively — grouped by category, with the real PHP call signature front and center, Discord's own description, and (where available) a real example payload — plus a "Try it out" button that fires a real request against your own bot.
cp harness/.env.example harness/.env # then fill in DISCORD_BOT_TOKEN / GUILD_ID
docker compose up -d --build
http://localhost:8081— Swagger UI.http://localhost:8080— the harness Laravel app itself (requires this package via a local path dependency, so it always runs against the currentsrc/, not a published release — edits tosrc/**/*.phpare picked up without rebuilding).
The HTTP routes Swagger calls only exist in this local test harness, as a thin proxy so "Try it out" works in a browser — they are not part of the published package. A real consumer of this package only ever calls the PHP methods shown in each Swagger entry's summary.
API Reference (core helpers)
All methods are static on Reysa\DiscordAPI\DAPI.
In a Laravel app you typically use the facade: Reysa\DiscordAPI\Facades\DAPI.
Below are the original hand-written convenience helpers. For the full set of ~200 additional
wrapped endpoints (organized under src/Concerns/*.php, one trait per Discord resource), browse
the Swagger UI (see above) or the source directly — method names mirror Discord's own endpoint
titles (e.g. "Get Guild Channels" → getGuildChannels()).
getGuildInvites(string $guildId): Response
Fetch all invites for a guild.
$invites = DAPI::getGuildInvites(config('discord-api.guild_id'));
deleteGuildInvite(string $code): Response
Delete a specific invite by code.
DAPI::deleteGuildInvite('inviteCodeHere');
getMessage(string $channelId, string $messageId): Response
Get a single message from a channel.
$message = DAPI::getMessage($channelId, $messageId);
getGuildUser(string $userId): Response
Get a guild member (by user ID) in the configured guild.
$member = DAPI::getGuildUser('123456789012345678');
getGuildRoles(): Response
Get the list of roles in the configured guild.
$roles = DAPI::getGuildRoles();
giveRole(string $userId, array $roleIds): Response[]
Give one or multiple roles to a member.
$roleIdsmust be an array of role IDs.- Discord's "Add Guild Member Role" endpoint only accepts one role per call
(
PUT /guilds/{guild.id}/members/{user.id}/roles/{role.id}), so this method sends one request per role ID. - Returns an array of
Responseobjects keyed by role ID (not a singleResponse), so you can check each role's outcome individually.
// Give a single role $results = DAPI::giveRole($userId, [123456789012345678]); // Give multiple roles $results = DAPI::giveRole($userId, [ 123456789012345678, 234567890123456789, 345678901234567890, ]); foreach ($results as $roleId => $response) { // $response->successful() / $response->json() per role }
removeRole(string $userId, array $roleIds): Response[]
Remove one or multiple roles from a member.
$roleIdsworks the same way as ingiveRole— oneDELETErequest per role ID.- Returns an array of
Responseobjects keyed by role ID.
// Remove a single role $results = DAPI::removeRole($userId, [123456789012345678]); // Remove multiple roles $results = DAPI::removeRole($userId, [ 123456789012345678, 234567890123456789, ]);
setName(string $userId, string $name): Response
Set the member's nickname in the configured guild.
DAPI::setName($userId, 'New Nickname');
sendMessageToUser(string $userId, string $message): Response|false
Send a direct message (plain text) to a user.
- Internally:
- Creates a DM channel with the user.
- Sends the message to that channel.
- Returns
falseif creating the DM channel fails.
$result = DAPI::sendMessageToUser($userId, 'Hello in your DMs!'); if ($result === false) { // handle failure }
sendEmbedMessageToUser(string $userId, array $payload): Response|false
Send a rich embed (or any valid Discord message payload) to a user via DM.
$payloadis sent as-is to the Discord API.- Example payload:
['embeds' => [...]] - Returns
falseif DM channel creation fails.
$payload = [ 'content' => 'Optional text', 'embeds' => [ [ 'title' => 'Hello!', 'description' => 'This is an embed message', 'color' => 0x7289DA, ], ], ]; DAPI::sendEmbedMessageToUser($userId, $payload);
sendMessageToChannel(string $channelId, array $payload): Response
Send a message to a specific channel.
$payloadcan be:['content' => 'plain text']- or a more complex structure (embeds, components, etc.).
DAPI::sendMessageToChannel('123456789012345678', [ 'content' => 'Hello channel!', ]);
getChannelMessage(string $channelId, string $messageId): Response
Retrieve a single message from a given channel.
$message = DAPI::getChannelMessage($channelId, $messageId);
getChannelMessages(string $channelId): Response
Retrieve recent messages from a given channel.
$messages = DAPI::getChannelMessages($channelId);
editChannelEmbedMessage(string $channelId, string $messageId, array $embeds): Response
Edit an existing message’s embeds in a channel.
DAPI::editChannelEmbedMessage($channelId, $messageId, [ [ 'title' => 'Updated title', 'description' => 'Updated description', ], ]);
Versioning & Roadmap
- Scope: Full coverage of Discord's documented bot-usable HTTP REST API. Request bodies are
passed through as-is (no validation), matching the original package's philosophy — see the
Discord docs or the Swagger UI (
docker compose up,http://localhost:8081) for exact payload shapes per endpoint. - Not covered: Gateway/WebSocket events, Discord Social SDK (Lobby) endpoints.
- Planned: Typed request/response DTOs and higher-level helpers on top of the raw wrappers.
Contributing
Issues and pull requests are welcome.
- Feel free to open an issue with:
- API endpoints you’d like to see supported
- Bug reports
- Ideas for improving developer experience (DX)
License
This project is open-source software licensed under the MIT license.
See the LICENSE file for details.