Skip to content

Rate limits

TEBHOS bounds HTTP API traffic with per-operation buckets and one global bucket. A bucket is an allowance of requests over a window. A request over the allowance is refused with 429, code set to RATE_LIMITED, a rate limit response object and the rate limit headers.

How buckets work

Every bucket is a leaky bucket. It admits at most its limit at once and then drains continuously at limit requests per window. A client that exhausts an allowance can send again as soon as enough of it has drained; it does not have to wait for the whole window.

For example, channel:message:create has a limit of 20 per 10 seconds. A client can send 20 messages in a burst, after which one more message is admitted roughly every 0.5 seconds.

The headers and the body report different instants

X-RateLimit-Reset and X-RateLimit-Reset-After report when the bucket will be completely empty. retry_after in the body reports the shorter delay after which one more request is admitted. Wait retry_after before retrying.

Buckets and keys

Most operations check a named bucket. The bucket name itself is not sent to clients; X-RateLimit-Bucket carries a stable 16-character hexadecimal hash of it, so a client can tell which operations share an allowance.

Each bucket is keyed by an identity, so separate callers have separate allowances. The key depends on the operation and is listed in the bucket tables:

Key Meaning
Account The authenticated user or bot
Account + channel, Account + guild The caller and the channel or guild in the path. Sending fast in one channel does not slow another
Client The Authorization header when one is sent, otherwise the client IP address
IP The client IP address. IPv4 addresses are used exactly; IPv6 addresses are grouped by their /64 network
Resource The resource in the path alone, shared by every caller (webhooks)

A bot and its owner are different accounts and never share an allowance.

Some operations check more than one bucket, for example login (per IP and per submitted login name) and group DM creation (the DM bucket plus an hourly group bucket). The request must pass every bucket.

A 429 can hide a 401 or 403

Buckets are checked early. A request whose credentials or permissions would be rejected can still receive 429 when its bucket is exhausted.

Global limit

Every request below /api/v1 also counts against a global bucket of 50 requests per second per client. The client is identified by its Authorization header, or by its IP address when it sends none.

These requests do not count against the global bucket:

  • CORS preflight (OPTIONS) requests.
  • GET and HEAD requests for public media such as avatars, icons and attachments.
  • GET and HEAD requests sent without an Authorization header.
  • Webhook execution (POST /webhooks/{webhook_id}/{token} and its integration variants) and webhook message read, edit and delete routes. They have their own per-webhook buckets.

A global denial has global: true in the body and the X-RateLimit-Global: true header. It never revokes the credential.

Rate limit response object

The 429 body has the members of the ordinary error response and two more.

Field Type Description
code string RATE_LIMITED
message string Human-readable text including the wait in whole seconds; may be localized
error string "429 Too Many Requests"
global boolean Whether the global bucket produced the denial
retry_after number The delay in fractional seconds before one more request is admitted, never below 0.001
{
  "error": "429 Too Many Requests",
  "code": "RATE_LIMITED",
  "message": "Hız sınırlamasına takıldın. 1 saniye sonra tekrar dene.",
  "global": false,
  "retry_after": 0.428
}

A slowmode denial answers 400 SLOWMODE_RATE_LIMITED instead.

Rate limit headers

TEBHOS sends rate limit headers only on a 429 response. A successful response carries none of them, so track your own request rate or simply handle 429.

Header Sent Description
Retry-After Every 429 The delay in whole seconds, rounded up, never below 1
X-RateLimit-Scope Every 429 user for a bucket denial, global for a global denial
X-RateLimit-Global Global 429 The literal value true
X-RateLimit-Limit Bucket 429 The bucket's capacity
X-RateLimit-Remaining Bucket 429 Always 0 on a denial
X-RateLimit-Reset Bucket 429 Unix time in seconds when the bucket is completely empty
X-RateLimit-Reset-After Bucket 429 Seconds, with a fractional part, until the bucket is completely empty
X-RateLimit-Bucket Bucket 429 Stable 16-character hexadecimal identifier of the bucket (not of the caller)

The API exposes these headers to cross-origin browser clients, so a web client can read them. The body's retry_after remains the most precise value.

HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Scope: user
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1790000010
X-RateLimit-Reset-After: 9.5
X-RateLimit-Bucket: 5f0c1d2e3a4b5c6d
Content-Type: application/json

Handling rate limits

async function tebhosFetch(url, init, attempts = 5) {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch(url, init);
    if (res.status !== 429) return res;
    const body = await res.json().catch(() => ({}));
    const waitSeconds = body.retry_after ?? Number(res.headers.get("Retry-After") ?? 1);
    await new Promise((r) => setTimeout(r, waitSeconds * 1000));
  }
  throw new Error("Rate limited too many times");
}
import time, requests

def tebhos_request(method, url, attempts=5, **kwargs):
    for _ in range(attempts):
        res = requests.request(method, url, **kwargs)
        if res.status_code != 429:
            return res
        try:
            wait = res.json().get("retry_after")
        except ValueError:
            wait = None
        time.sleep(wait or float(res.headers.get("Retry-After", 1)))
    raise RuntimeError("Rate limited too many times")

Slowmode

Slowmode limits how often one account sends a message in one guild channel. The allowance is one message per rate_limit_per_user seconds configured on the channel, counted separately for each account and channel. It applies only in guild channels whose interval is above zero, and a member holding BYPASS_SLOWMODE (which includes the guild owner and ADMINISTRATOR) is exempt.

A denied send returns 400 SLOWMODE_RATE_LIMITED, not 429, with a top-level retry_after in fractional seconds and a Retry-After header in whole seconds. It has no X-RateLimit-* header, so a client can tell it apart from a bucket denial by the status and the code.

{
  "error": "400 Bad Request",
  "code": "SLOWMODE_RATE_LIMITED",
  "message": "Yavaş mod hız sınırı.",
  "retry_after": 3.2
}

Limits answering 400

Profile field changes are limited to 25 changes per 30 minutes per field. The limit applies separately to the account profile and to each guild member profile. A denial answers 400 INVALID_FORM_BODY with one entry in errors whose code names the field. It has no retry_after and no rate limit header; the remaining wait appears only in the human-readable message.

Field Validation code
Biography BIO_CHANGED_TOO_MANY_TIMES
Pronouns PRONOUNS_CHANGED_TOO_MANY_TIMES
Accent colour ACCENT_COLOR_CHANGED_TOO_MANY_TIMES
Avatar AVATAR_CHANGED_TOO_MANY_TIMES
Banner BANNER_CHANGED_TOO_MANY_TIMES

Bucket reference

The tables below list every bucket, with its limit, window and key. Limits are fixed in the API and apply to every account; there is no per-account exemption. Rate limiting can only be switched off in a local development build, never on the production instance.

Authentication

Bucket Limit Window Key Operations
auth:login 10 10 s IP Log in
auth:login:email 5 15 min Submitted login name Log in
login:ip 10 30 min IP Log in
auth:login:mfa 5 60 s IP Complete login with TOTP, backup code, SMS or WebAuthn, and get WebAuthn MFA options
auth:login:mfa:sms:send 3 60 s IP Send an SMS login code
auth:register 10 10 s IP Register, get username suggestions
registration:email 3 15 min Submitted email Register
registration:ip 3 1 h IP Register
registration:subnet 15 1 h IPv4 /24 or IPv6 /48 Register
auth:send-verification 3 3 min IP Send registration verification code
auth:send-verification-email 1 60 s Submitted email Send registration verification code
auth:check-email 20 60 s IP Check email availability
auth:check-username 20 60 s IP Check username availability
auth:forgot 5 60 s IP Request password recovery
password_reset:ip 20 30 min IP Request password recovery
password_reset:email 5 30 min Submitted email Request password recovery
auth:reset:validate 20 60 s IP Validate a password reset token
auth:reset 10 60 s IP Reset a password
auth:verify 10 60 s IP Verify an email address
auth:email_revert 10 60 s IP Revert an email change
auth:authorize_ip 5 60 s IP Authorize a new login location
auth:ip_authorization_resend 5 60 s IP Resend the location authorization email
auth:ip_authorization_poll 60 60 s IP Poll location authorization
auth:webauthn:options 20 10 s IP Get passkey login options
auth:webauthn:authenticate 10 10 s IP Log in with a passkey
auth:sso:start 10 10 s IP Get single sign-on status, start single sign-on
auth:sso:complete 15 10 s IP Complete single sign-on
auth:handoff:initiate 10 60 s Client Start a desktop login handoff
auth:handoff:info 10 60 s Client Get handoff information
auth:handoff:complete 10 60 s Client Complete a handoff
auth:handoff:cancel 10 60 s Client Cancel a handoff
auth:handoff:status 60 60 s Client Poll handoff status
auth:logout 20 10 s Client Log out
auth:sessions 40 10 s Account List sessions
auth:sessions:logout 20 10 s Account End one, several, other or all sessions
auth:sudo 5 10 s IP Create a sudo grant
auth:sudo_pwd 10 5 min Account Password sudo verification
auth:sudo_mfa 10 15 min Account MFA sudo verification
sudo:mfa:methods 20 60 s Account List sudo methods
sudo:webauthn:options 10 60 s Account Get passkey sudo options
auth:pk_assert 10 5 min Account Passkey assertion for sudo

Account security

Bucket Limit Window Key Operations
user:email_change:start 10 60 s Account Start an email change
email_change:orig / auth:emailchg_start 3 15 min Account Start an email change, resend the code to the original address
user:email_change:resend_original 10 60 s Account Resend the code to the original address
user:email_change:verify_original 20 60 s Account Verify the original address
user:email_change:request_new 10 60 s Account Request the new address
user:email_change:resend_new 10 60 s Account Resend the code to the new address
email_change:new / auth:emailchg_new 5 15 min Account Request the new address, resend the new code, bounced-address recovery sends
user:email_change:verify_new 20 60 s Account Verify the new address
user:email_change:apply 20 60 s Account Complete an email change
user:email_change:bounced:request_new 10 60 s Account Bounced email: request a new address
user:email_change:bounced:resend_new 10 60 s Account Bounced email: resend the new code
user:email_change:bounced:verify_new 20 60 s Account Bounced email: verify the new address
user:password_change:start 10 60 s Account Start a password change
auth:pwdchg_start 3 15 min Account Start a password change
user:password_change:resend 10 60 s Account Resend the password change code
auth:pwdchg_resend / password_change:resend 3 15 min Account Resend the password change code
user:password_change:verify 20 60 s Account Verify the password change code
user:password_change:complete 10 60 s Account Complete a password change
user:mfa:totp:enable 10 60 s Account Enable TOTP, verify a TOTP code
user:mfa:totp:disable 10 60 s Account Disable TOTP
user:mfa:backup_codes 6 60 s Account List or regenerate backup codes
mfa:webauthn:list 40 10 s Account List passkeys and WebAuthn credentials
mfa:webauthn:registration_options 20 10 s Account Get passkey registration options
mfa:webauthn:register 10 60 s Account Register a passkey
mfa:webauthn:update 20 10 s Account Rename a passkey
mfa:webauthn:delete 10 60 s Account Delete a passkey
phone:send_verification 5 60 s Account Enrol or resend SMS two-factor authentication
phone:verify_code 10 60 s Account Verify a phone or SMS two-factor code
user:authorized_ips:forget 10 60 s Account Forget authorized login locations
user:account:disable 5 1 h Account Disable the account
user:account:delete 5 1 h Account Delete the account
user:data:harvest 5 30 min Account Request a data export
user:harvest:status 40 10 s Account Get a data export
user:harvest:latest 40 10 s Account Get the latest data export
user:harvest:download 10 60 s Account Download a data export
profile:purge 3 1 h Account Delete all of one's own messages
user:messages:bulk_delete_mine_filtered 5 30 min Account Delete one's own messages with filters

Users and relationships

Bucket Limit Window Key Operations
user:read 100 10 s Client + target user Get a user
user:profile 100 10 s Account + target user Get a user profile
user:update 20 60 s Account Modify the current user profile, accept terms
username_change 5 3 h Account Change username
user:check_tag 60 10 s Account Check tag availability
user:settings:get 40 10 s Account Get the current user, get user settings
user:settings:update 20 10 s Account Modify user settings, modify voice activity sharing
user:guild_settings:update 30 10 s Account Modify per-guild notification settings
user:notes:read 60 10 s Account List and get user notes
user:notes:write 40 10 s Account Set a user note
user:relationships:list 40 10 s Account List relationships
user:friend_request:send 10 60 s Account Send a friend request by username or ID
user:friend_request:accept 20 10 s Account Accept a friend request, change a relationship
user:relationship:update 30 10 s Account Set a friend nickname
user:relationship:delete 30 10 s Account Remove a relationship
relationship:bulk_ignore 5 60 s Account Ignore friend requests in bulk
user:channels 40 10 s Account List and open private channels, pin and unpin DMs
user:group_dm:create 10 1 h Account Create a group DM (in addition to user:channels)
user:group_dm:recipient:add 10 1 h Account Add a group DM recipient (in addition to channel:update)
user:preload_messages 40 10 s Account Preload DM messages
user:mentions:read 40 10 s Account List recent mentions
user:mentions:delete 60 10 s Account Dismiss one or all mentions
user:saved_messages:read 40 10 s Account List saved messages
user:saved_messages:write 30 10 s Account Save and unsave messages
user:push:list 40 10 s Account List push subscriptions and devices
user:push:subscribe 20 60 s Account Subscribe, rotate, register a mobile device
user:push:unsubscribe 40 60 s Account Unsubscribe, remove a device
user:entrance_sound:list 30 60 s Account List entrance sounds
user:entrance_sound:upload 5 5 min Account Upload an entrance sound
user:entrance_sound:mutate 20 60 s Account Rename, delete or select an entrance sound
voice:entrance_sound:play 3 30 s Account + channel Play an entrance sound
favorite_meme:list 60 10 s Account List saved media
favorite_meme:get 100 10 s Account Get saved media
favorite_meme:update 30 10 s Account Modify saved media
favorite_meme:delete 30 10 s Account Delete saved media
connection:list 60 60 s Account List connections
connection:create 5 60 s Account Start a connection, authorize a Bluesky connection
connection:verify 5 60 s Account Verify a connection
connection:verify_and_create 5 60 s Account Verify and create a connection
connection:update 30 60 s Account Modify and reorder connections
connection:delete 10 60 s Account Delete a connection
theme:share:create 20 60 s Client Share a theme

Channels and messages

Bucket Limit Window Key Operations
channel:read 100 10 s Account + channel Get a channel, get slowmode state, list voice regions
channel:update 20 10 s Account + channel Modify a channel, set or delete a permission overwrite, add or remove a group DM recipient
channel:delete 20 10 s Account + channel Delete or close a channel
guild:channel:create 10 60 s Account + guild Create a guild channel
channel:messages:read 100 10 s Account + channel List channel messages
channel:message:read 100 10 s Account + channel Get a message
channel:messages:bulk_read 20 10 s Account Fetch messages from several channels
channel:message:create 20 10 s Account + channel Create a message
channel:message:update 20 10 s Account + channel Edit a message
channel:message:delete 20 10 s Account + channel Delete a message, delete an attachment
channel:message:bulk_delete 10 10 s Account + channel Bulk delete messages, bulk delete one's own messages
channel:message:purge 2 60 s Account + channel Purge personal notes
channel:message:ack 100 10 s Account + channel Acknowledge a message
read_state:ack_bulk 20 10 s Account Acknowledge several channels
channel:read_state:delete 40 10 s Account + channel Clear a read state
channel:pins 20 10 s Account + channel List pins, pin, unpin, acknowledge pins
channel:reactions 30 10 s Account + channel Add, remove and list reactions
channel:typing 20 10 s Account + channel Trigger the typing indicator
channel:attachment:upload 10 10 s Account + channel Request attachment upload URLs, complete multipart uploads
search:messages 20 10 s Account Search messages
channel:call:get 60 10 s Account + channel Get call eligibility
channel:call:ring 5 10 s Account + channel Ring call recipients
channel:call:stop_ringing 20 10 s Account + channel Stop ringing
channel:call:update 10 10 s Account + channel Update or end a call
voice:state 120 60 s Account Update voice state
channel:stream:update 20 10 s Account + stream Update a stream region
channel:stream:preview:get 60 10 s Account + stream Get a stream preview
stream:preview:upload_url 20 10 s Stream Create a stream preview upload URL
stream:preview:post 20 10 s Stream Upload a stream preview
stream:preview:delete 20 10 s Stream Delete a stream preview

Guilds

Bucket Limit Window Key Operations
guild:list 40 10 s Account List the current user's guilds
guild:create 10 60 s Account Create a guild
guild:read 100 10 s Account + guild Get a guild
guild:update 20 10 s Account + guild Modify a guild, transfer ownership
guild:delete 10 60 s Account + guild Delete a guild
guild:leave 10 10 s Account + guild Leave a guild, delete one's own messages in a guild
guild:channels:list 60 10 s Account + guild List guild channels
guild:channel:positions 30 10 s Account + guild Modify channel positions
guild:members 40 10 s Account + guild List, get and search members, list bans
guild:member:update 20 10 s Account + guild Modify a member, modify the current member
guild:member:remove 20 10 s Account + guild Kick, ban, unban
guild:member:role:add 20 10 s Client + guild Add a role to a member
guild:member:role:remove 20 10 s Account + guild Remove a role from a member
guild:role:list 60 10 s Account + guild List roles
guild:role:create 10 60 s Account + guild Create a role
guild:role:update 20 10 s Account + guild Modify a role
guild:role:delete 10 60 s Account + guild Delete a role
guild:role:positions 20 10 s Account + guild Modify role positions
guild:role:hoist_positions 20 10 s Account + guild Modify role hoist positions
guild:role:hoist_positions_reset 10 60 s Account + guild Reset role hoist positions
guild:audit_logs 20 10 s Account + guild List audit log entries
guild:vanity_url:get 100 10 s Account + guild Get the vanity URL
guild:vanity_url:patch 10 60 s Client + guild Modify the vanity URL
guild:emojis:list 60 10 s Account + guild List emojis
guild:emoji:create 10 30 s Account + guild Create an emoji
guild:emoji:clone 10 30 s Account + guild Clone an emoji
guild:emoji:bulk_create 6 60 s Account + guild Create emojis in bulk
guild:emoji:update 20 10 s Account + guild Modify an emoji
guild:emoji:delete 10 30 s Account + guild Delete an emoji
guild:emoji:metadata 60 10 s Client Get emoji metadata
guild:sticker:list 60 10 s Account + guild List stickers
guild:sticker:create 10 30 s Account + guild Create a sticker
guild:sticker:clone 10 30 s Account + guild Clone a sticker
guild:sticker:bulk_create 6 60 s Account + guild Create stickers in bulk
guild:sticker:update 20 10 s Account + guild Modify a sticker
guild:sticker:delete 10 30 s Account + guild Delete a sticker
guild:sticker:metadata 60 10 s Client Get sticker metadata
invite:read 100 10 s Client + invite code Get an invite
invite:accept 10 10 s Account Accept an invite, join a public guild
invite:create 20 60 s Account + channel Create an invite
invite:list 40 10 s Account + channel or guild List channel or guild invites
invite:delete 20 10 s Account + invite code Delete an invite
discovery:search 30 10 s Client Search discoverable guilds
discovery:categories 60 10 s Client List discovery categories
discovery:status 30 10 s Account + guild Get discovery status
discovery:apply 5 60 s Account + guild Apply, edit or withdraw a discovery application
discovery:join 10 60 s Account Join a guild from discovery

Webhooks

Webhook buckets are keyed by the webhook, channel or guild in the path, so every caller shares them.

Bucket Limit Window Key Operations
webhook:list_guild 40 10 s Guild List guild webhooks
webhook:list_channel 40 10 s Channel List channel webhooks
webhook:create 10 60 s Channel Create a webhook
webhook:read 100 10 s Webhook Get a webhook, with or without token
webhook:update 20 10 s Webhook Modify a webhook, with or without token
webhook:delete 20 10 s Webhook Delete a webhook, with or without token
webhook:execute 60 60 s Webhook Execute a webhook, execute a Slack-compatible webhook
webhook:github 200 60 s Webhook Execute a GitHub-compatible webhook
webhook:instatus 200 60 s Webhook Execute an Instatus-compatible webhook
webhook:message_get 60 60 s Webhook Get a webhook message
webhook:message_edit 30 60 s Webhook Edit a webhook message
webhook:message_delete 30 60 s Webhook Delete a webhook message

Applications, OAuth2 and Gateway

Bucket Limit Window Key Operations
oauth_dev:clients:create 10 1 h Account Create an application
oauth_dev:clients:list 60 60 s Account or client List own applications, get an application, get public application metadata, list authorized applications
oauth_dev:clients:update 30 60 s Application Modify an application, modify its bot profile
oauth_dev:clients:rotate_secret 10 1 h Application Reset the bot token, reset the client secret
oauth_dev:clients:delete 10 1 h Application Delete an application
oauth:authorize 60 60 s IP Get authorization details, submit consent
oauth:token 120 60 s IP Exchange or refresh a token
oauth:introspect 120 60 s Client, IP or account Introspect and revoke tokens, get user info, revoke authorizations
gateway:bot_info 60 60 s Client Get Gateway information for a bot
instance:info 60 60 s Client Get instance discovery

Other

Bucket Limit Window Key Operations
gif:search 40 10 s Client Search GIFs
gif:trending 40 10 s Client List trending GIFs
gift:get 60 10 s Client Get a gift
gift:redeem 10 60 s Account Redeem a gift
gifts:list 40 10 s Account List the current user's gifts
report 10 1 h Account Report a message, user or guild, create a report
premium:cancel 10 1 h Account Cancel premium
premium:cancel-subscription 5 60 s Account Cancel a subscription at period end
premium:reactivate-subscription 5 60 s Account Reactivate a subscription
premium:portal 20 1 h Account Open the billing portal
business:checkout 10 1 h Account Start a business plan checkout
business:portal 20 1 h Account Open the business billing portal
business:cancel 10 1 h Account Cancel or reactivate a business plan
business:affiliate 30 1 h Account Create an affiliation request

Other surfaces

The Gateway has its own limits for identifies, commands and payload sizes; see Gateway limits and rate limits. Uploading bytes to an upload URL is not rate limited by count, but the URL expires; see Attachment uploads.