API Reference
An overview of how the Fluxer API works and how to use it
Fluxer exposes an HTTP API for most of the read and write operations in the app. You can use it to build bots, automations, and integrations that talk to Fluxer from your code. For real-time events, connect to the Fluxer Gateway over WebSocket.
If you've used the Discord API before, Fluxer will feel familiar. In many cases you can adapt existing Discord bot libraries to work with Fluxer with only small changes.
Base URL
All HTTP API requests go through the same base URL:
https://api.fluxer.appAPI Versioning
Fluxer uses versioned API endpoints. The current version is v1, and all documented endpoints are prefixed with /v1/.
GET /v1/...If you omit the version prefix, you'll hit the latest stable version. That can change over time, so for anything you care about not breaking, it's better to pin a specific version like /v1/.
Error Responses
Generic Error Response
When a request fails, the API returns an HTTP status code plus a JSON body with error details:
{
"code": "UNKNOWN_USER",
"message": "Unknown User"
}code is a machine-readable error string. message is meant for humans and may change, so don't rely on it for program logic.
Form Validation Errors
For endpoints that accept form data, failed validation returns 400 Bad Request and a list of field-level errors:
{
"code": "INVALID_FORM_BODY",
"message": "Input Validation Error",
"errors": [
{"path": "username", "message": "Username must be at least 3 characters long."},
{"path": "email", "message": "Email must be a valid email address."}
]
}For nested structures, path uses dot and index notation to point at the field that failed:
{
"code": "INVALID_FORM_BODY",
"message": "Input Validation Error",
"errors": [
{"path": "profile.address.street", "message": "Street is required."},
{"path": "items.0.quantity", "message": "Quantity must be a positive integer."}
]
}Treat code as the stable part of the error and use errors[*].path to locate invalid inputs.
Authentication
Most API requests require authentication. Send your bot token in the Authorization header:
Authorization: Bot YOUR_BOT_TOKENReplace YOUR_BOT_TOKEN with the token from User Settings > Developer Applications in the Fluxer web/desktop app.
Bot tokens are secret. Don't commit them to source control or ship them in client-side code.
Encryption
All HTTP and WebSocket connections to Fluxer must use TLS (https:// and wss://). The minimum supported version is TLS 1.2.
Plain http:// and ws:// endpoints are not available.
Snowflakes
Fluxer uses Twitter Snowflakes as IDs for users, messages, channels, and other entities.
Within a single entity type (for example, messages), Snowflakes are unique. Different entity types may happen to share the same numeric Snowflake, so always keep track of what an ID refers to.
Snowflakes are 64-bit unsigned integers that encode a timestamp plus some extra bits. In JSON, they're always sent as strings to avoid precision issues in languages that don't handle 64-bit integers well. Treat them as opaque strings unless you explicitly need to decode them.
| Component | Bits | Description |
|---|---|---|
| Timestamp | 42 | Milliseconds since the Fluxer epoch (1420070400000, the first second of 2015) |
| Worker ID | 5 | ID of the worker that generated the Snowflake |
| Process ID | 5 | ID of the process that generated the Snowflake |
| Sequence Number | 12 | Counter for IDs generated in the same millisecond |
If you decode the timestamp part, you can tell when a resource was created.
function snowflakeToTimestamp(snowflake: string): number {
const fluxerEpoch = 1420070400000n;
const timestamp = (BigInt(snowflake) >> 22n) + fluxerEpoch;
return Number(timestamp);
}Pagination with Snowflakes
Many API endpoints return lists of items. To help you paginate through large result sets, these endpoints accept before, after, and limit query parameters. Check the individual endpoint docs to see which ones support pagination.
Because Snowflake IDs encode timestamps, you can also generate Snowflakes from timestamps to paginate by time:
function timestampToSnowflake(timestamp: number): string {
const fluxerEpoch = 1420070400000n;
const snowflake = (BigInt(timestamp) - fluxerEpoch) << 22n;
return snowflake.toString();
}
const currentTimeMs = Date.now();
const currentSnowflake = timestampToSnowflake(currentTimeMs);To specify the beginning of time, use the Snowflake 0.
ISO 8601 Timestamps
Timestamps in Fluxer API responses use the ISO 8601 format with UTC timezone. You can parse them with standard libraries in your language of choice.
Nullable & Optional Fields
To stay close to Discord's API docs, the Fluxer API docs use this convention for nullable and optional fields in tables:
| Field Name | Type | Description |
|---|---|---|
optional_field? | string | An optional field that may be missing in the response |
nullable_field | ?string | A nullable field that may be null in the response, but is always present |
optional_nullable_field? | ?string | An optional field that may be missing or null in the response |
Backwards Compatibility
New fields added to responses, documented or not, are considered backwards-compatible additions. Your client should ignore any fields it doesn't recognize.
Breaking changes to the API will be announced in advance, and a migration period will be provided where both the old and new versions of the API are available.
HTTP API
User Agent
When making HTTP requests to the Fluxer API, it's good practice to set a custom User-Agent header that identifies your application. Example:
User-Agent: MyFluxerBot ($url, $version)Content Type
Set the Content-Type header to application/json, application/x-www-form-urlencoded, or multipart/form-data as appropriate for the request body you're sending.
Rate Limits
Rate limits are reported via HTTP headers in the response. If you exceed a rate limit, you'll receive a 429 Too Many Requests response. For more details, see the Rate Limits documentation.
Gateway API (WebSocket)
Fluxer's Gateway API lets you maintain a long-lived WebSocket connection for real-time events. For details on how to connect and interact with the Gateway, see the Gateway API documentation.
Message Formatting
Fluxer supports rich message formatting using Markdown-style syntax. Compatibility with most Discord-flavored Markdown is intentional so you can port bots and integrations with minimal changes.
Format Types
In addition to standard formatting such as bold, italics, underline, strikethrough, inline code, code blocks, blockquotes, headings, lists, and links, Fluxer supports the following formatting options:
| Type | Syntax | Example |
|---|---|---|
| Spoiler | ||text|| | ||spoiler|| (hidden until clicked) |
| Subtext (small gray text) | -# your text | -# extra context / footnote |
| Email link | <hello@example.com> | <hello@example.com> |
| Phone link | <+1234567890> | <+1234567890> |
| Mention user | <@user_id> | <@123456789012345678> |
| Mention channel | <#channel_id> | <#123456789012345678> |
| Mention role | <@&role_id> | <@&123456789012345678> |
| Standard emoji | Unicode emoji | 😄 |
| Custom emoji | <:name:emoji_id> | <:custom_emoji:123456789012345678> |
| Custom emoji (animated) | <a:name:emoji_id> | <a:animated_emoji:123456789012345678> |
| Unix timestamp | <t:timestamp> | <t:1445444940> |
| Unix timestamp (styled) | <t:timestamp:style> | <t:1445444940:R> |
Timestamp Styles
When using Unix timestamps, you can specify a style character to control how the timestamp is displayed:
| Style | Description | Example Output |
|---|---|---|
t | Short time | 16:29 |
T | Medium time | 16:29:00 |
d | Short date | 10/21/2015 |
D | Long date | October 21, 2015 |
f* | Long date, short time | October 21, 2015 at 16:29 |
F | Full date, short time | Wednesday, October 21, 2015 at 16:29 |
s | Short date, short time | 10/21/2015, 16:29 |
S | Short date, medium time | 10/21/2015, 16:29:00 |
R | Relative time | 2 hours ago |
* Default if no style is provided.
User Content CDN
Base URL
https://fluxerusercontent.comAll user-uploaded media content is served through the User Content CDN at the above base URL.
CDN Endpoints
| Resource Type | Path Template | Supported Formats |
|---|---|---|
| User Avatar | /avatars/{user_id}/{avatar_hash}.{ext} | PNG, JPEG, WebP, GIF |
| Guild Icon | /icons/{guild_id}/{icon_hash}.{ext} | PNG, JPEG, WebP, GIF |
| Guild Banner | /banners/{guild_id}/{banner_hash}.{ext} | PNG, JPEG, WebP, GIF |
| Guild Splash | /splashes/{guild_id}/{splash_hash}.{ext} | PNG, JPEG, WebP, GIF |
| Custom Emoji | /emojis/{emoji_id}.{ext} | PNG, JPEG, WebP, GIF |
| Sticker | /stickers/{sticker_id}.{ext} | WebP, GIF |
| Guild Member Avatar | /guilds/{guild_id}/users/{user_id}/avatars/{avatar_hash}.{ext} | PNG, JPEG, WebP, GIF |
| Guild Member Banner | /guilds/{guild_id}/users/{user_id}/banners/{banner_hash}.{ext} | PNG, JPEG, WebP, GIF |
| Attachment | /attachments/{channel_id}/{attachment_id}/{filename} | Various |
All CDN endpoints support query parameters for dynamic image transformation and optimization.
Query Parameters
CDN endpoints support the following query parameters for transforming and optimizing media on the fly:
Avatar, Icon, Banner, Splash, and Emoji Endpoints
These endpoints support the ImageQuerySchema:
| Parameter | Type | Default | Description |
|---|---|---|---|
size | integer | 128 | The desired width in pixels. Must be one of: 16, 20, 22, 24, 28, 32, 40, 44, 48, 56, 60, 64, 80, 96, 100, 128, 160, 240, 256, 300, 320, 480, 512, 600, 640, 1024, 1280, 1536, 2048, 3072, 4096. The image will be resized proportionally. |
quality | string | high | Image quality preset. Options: high (80% quality), low (20% quality), lossless (100% quality). |
animated | boolean | false | Whether to preserve animation for WebP images. Note: GIF images are always animated regardless of this parameter. |
Attachment Endpoints
Attachment endpoints support more flexible transformations via the ExternalQuerySchema:
| Parameter | Type | Default | Description |
|---|---|---|---|
width | integer | - | The desired width in pixels (1-4096). If only width is specified, height is calculated to maintain aspect ratio. |
height | integer | - | The desired height in pixels (1-4096). If only height is specified, width is calculated to maintain aspect ratio. |
format | string | - | Convert the image to the specified format. Options: png, jpg, jpeg, webp, gif. |
quality | string | lossless | Image quality preset. Options: high (80% quality), low (20% quality), lossless (100% quality). |
animated | boolean | false | Whether to preserve animation for GIF and WebP images. Must be set to true to preserve animation in attachments. |
For attachment endpoints, if no transformations are specified (no width, height, format, or quality other than lossless), the original file is served directly.
Examples
# Get a 256px user avatar in high quality
https://fluxerusercontent.com/avatars/123456789012345678/a_abc123.webp?size=256&quality=high
# Get an animated guild icon
https://fluxerusercontent.com/icons/123456789012345678/a_def456.gif?size=512&animated=true
# Get an attachment resized to 800x600 in WebP format
https://fluxerusercontent.com/attachments/123/456/image.png?width=800&height=600&format=webp
# Stream a video attachment without transformation
https://fluxerusercontent.com/attachments/123/456/video.mp4Static Assets CDN
Base URL
https://fluxerstatic.comDefault avatars can be accessed through the Static Assets CDN at the above base URL.
CDN Endpoints
| Resource Type | Path Template | Supported Formats |
|---|---|---|
| Default Avatar | /avatars/{index}.png* | PNG |
* {index} is a number from 0 to 5, representing the six default avatar options. Use index = user_id % 6 to select a default avatar based on the user's ID.
function getDefaultAvatarUrl(userId: string): string {
const index = Number(BigInt(userId) % 6n);
return `https://fluxerstatic.com/avatars/${index}.png`;
}Image Data
Image data is a data URI scheme supporting PNG, JPEG, WebP, and GIF formats. It consists of a prefix indicating the media type and encoding, followed by the base64-encoded image data.
data:image/{format};base64,{base64_data}Replace {format} with the actual image format (for example, png, jpeg, webp, gif) and {base64_data} with the base64-encoded string of the image.
Uploading Files
The file upload size limit applies to each file in a request. The default limit is 25 MiB for free users and 500 MiB for premium users. At most 10 files can be uploaded in a single message.
Multipart Form Data Upload
Upload files directly with your message using multipart/form-data:
const form = new FormData();
form.append(
'payload_json',
JSON.stringify({
content: 'Check out these files!',
attachments: [
{id: 0, filename: 'cat.png', description: 'A cute cat'},
{id: 1, filename: 'dog.jpg', description: 'A good dog'},
],
}),
);
form.append('files[0]', catImageBlob, 'cat.png');
form.append('files[1]', dogImageBlob, 'dog.jpg');
const response = await fetch('https://api.fluxer.app/v1/channels/123456789012345678/messages', {
method: 'POST',
headers: {
Authorization: 'Bot YOUR_BOT_TOKEN',
},
body: form,
});Editing Messages with Attachments
Existing attachments must be specified when PATCHing messages with new attachments. Any attachments not specified will be removed and replaced with the specified list. If you don't specify attachments at all, the existing attachments will remain unchanged.
Using Attachments in Embeds
Use the special attachment://{filename} URL format to reference uploaded files within embed objects.
Only PNG, JPEG, WebP, and GIF image formats may be used at this time. Other file types are not supported.
{
"embeds": [
{
"title": "Look at this image",
"image": {
"url": "attachment://cat.png"
}
}
]
}