Skip to content

Synertry/discord-api-proxy

Repository files navigation

Discord API Proxy

CI Deploy TypeScript Cloudflare Workers Hono License: BSL-1.0

A reverse proxy for the Discord API, deployed as a Cloudflare Worker. Adds authentication, token management, snowflake validation, and server-specific business logic endpoints on top of the standard Discord API. Original motivation was for my Google Sheets to be able to call the Discord API, without my requests being rejected from Discord, because they would detect Google's IP addresses.

Features

  • Reverse proxy - Forwards any request to https://discord.com/api/v10 with automatic token injection
  • Dual token support - Switches between bot and user tokens based on the endpoint or an explicit header
  • Snowflake validation - Validates Discord IDs in URL paths before forwarding, returning Discord-compatible error responses
  • Rate limit interception - Reformats 429 responses into a consistent JSON envelope
  • Custom endpoints - Server-specific business logic that processes Discord data server-side
  • OpenAPI spec - Auto-generated via @hono/zod-openapi with Swagger UI

Tech Stack

Component Technology
Runtime Cloudflare Workers
Framework Hono + @hono/zod-openapi
Language TypeScript (strict mode)
Validation Zod
Testing Vitest + @cloudflare/vitest-pool-workers
Package Manager Bun

Getting Started

Prerequisites

Installation

bun install

Environment Setup

Create a .dev.vars file in the project root with your secrets:

DISCORD_TOKEN_BOT=your-bot-token
DISCORD_TOKEN_USER=your-user-token
AUTH_KEY=your-api-key

Caution

I advise to use an alt account for the user token to avoid any future risks for your main account of being banned by Discord.

Development

bun run lint       # Type check (tsc --noEmit)
bun run test       # Run all tests
bun run dev        # Start local dev server via Wrangler

Architecture

Middleware Sieve

Requests flow through a layered middleware pipeline before reaching route handlers:

Request
  |
  v
[Rate Limit Interceptor]  Reformats 429 responses (post-processing)
  |
  v
[Auth Middleware]          Validates x-auth-key or Authorization header
  |
  v
[Discord Context]          Selects bot/user token and User-Agent
  |
  v
[Snowflake Validator]      Validates Discord IDs in URL path segments
  |
  v
[Custom Routes]            /custom/* - Business logic endpoints
  |
  v
[Proxy Forwarder]          /* - Catch-all to discord.com/api/v10

Note

In simple terms, we can add custom endpoints even under /custom, if nothing matches, then we forward it to the official API.

Token Selection

The proxy selects which Discord token to use based on:

  1. x-proxy-context: user header - Forces user token
  2. x-proxy-context: bot header - Forces bot token
  3. Path heuristic (default) - Paths containing /guilds use user token; everything else uses bot token

User token requests also receive a browser-like User-Agent header.

Project Structure

src/
  index.ts                    App factory and middleware sieve
  types.ts                    Shared type definitions (Bindings, DiscordUser)
  global.d.ts                 Build-time constants (BUILD_HASH, BUILD_TIMESTAMP)
  middleware/
    auth.ts                   API key authentication
    discord-context.ts        Token selection and User-Agent injection
    snowflake-validator.ts    Discord ID format validation
  routes/
    proxy.ts                  Catch-all Discord API reverse proxy
    custom.ts                 Custom business logic route tree
  custom/
    chillzone/events/
      kindness-cascade/       Kindness Cascade tallying module (see its own README)

test/
  env.d.ts                    Cloudflare test type augmentation
  middleware/                 Unit tests for each middleware
  routes/                    Integration tests for proxy and custom routes
  custom/chillzone/events/
    kindness-cascade/         Classifier, tallier, formatter, and handler tests

Custom Endpoints

Kindness Cascade

Tallies submissions for the ChillZone server's Kindness Cascade event. Fetches all messages from a channel, classifies each one, and returns ranked leaderboards.

GET /custom/chillzone/events/kindness-cascade?guildId={id}&channelId={id}
GET /custom/chillzone/events/kindness-cascade?guildId={id}&channelId={id}&formattedMessage=true

See src/custom/chillzone/events/kindness-cascade/README.md for full documentation.

Cupid's Inbox

GET /custom/chillzone/events/cupids-inbox

Returns { "tally": 0 }. Placeholder for now. Not yet imported from my private project.

Testing

bun run test           # Run all 88 tests across 10 suites
bun run test -- --ui   # Open Vitest UI

Tests use @cloudflare/vitest-pool-workers to run in a Workers-compatible runtime. Discord API calls are mocked at the fetch level.

Deployment

Deployment is handled by a three-stage CI/CD pipeline:

  1. Push to mainci.yaml runs linting and tests. Dependabot dependency bumps are auto-merged directly to production.
  2. Pre-production reviewpre-production-review.yaml generates a change report and requests reviewer approval via the status/approved label.
  3. Deploydeploy.yaml triggers on push to production, uploading and promoting the Worker via Wrangler's gradual deployment (wrangler versions uploadwrangler versions deploy).

Required Secrets

Set these in your repository settings under Settings → Secrets and variables → Actions:

Secret Where to get it
CLOUDFLARE_API_TOKEN Cloudflare Dashboard → My Profile → API Tokens — create a token with the Edit Cloudflare Workers template
CLOUDFLARE_ACCOUNT_ID Cloudflare Dashboard → select your account → copy the Account ID from the right sidebar on the overview page
CUSTOM_DOMAIN Your Cloudflare Workers custom domain (e.g. api.example.com). Injected into wrangler.jsonc at deploy time via the __CUSTOM_DOMAIN__ placeholder
PAT GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens — needs Contents: Read and write and Pull requests: Read and write permissions for this repo. Required because pushes made with the default GITHUB_TOKEN do not trigger downstream workflows

About

Authenticated Discord API reverse proxy on Cloudflare Workers

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors