fluxer/fluxer_docs/content/docs/api-reference.mdx
2026-01-01 21:05:54 +00:00

387 lines
17 KiB
Plaintext

---
title: API Reference
description: An overview of how the Fluxer API works and how to use it
---
Fluxer exposes an HTTP API for most read/write operations. 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](https://discord.dev), Fluxer should feel familiar. Most Discord libraries adapt with only small tweaks (for example, changing the base URL).
## Base URL
All HTTP API requests go through the same base URL:
```text
https://api.fluxer.app
```
## API Versioning
Fluxer uses versioned API endpoints. The current version is `v1`, and all documented endpoints are prefixed with `/v1/`.
```text
GET /v1/...
```
If you omit the version prefix, you'll hit the latest stable version. That can change over time, so pin a version like `/v1/` for anything you don't want to break unexpectedly.
## Error Responses
### Generic Error Response
When a request fails, the API returns an HTTP status code plus a JSON body with error details:
```json
{
"code": "UNKNOWN_USER",
"message": "Unknown User"
}
```
`code` is stable and machine-readable. `message` is 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:
```json
{
"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:
```json
{
"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:
```text
Authorization: Bot YOUR_BOT_TOKEN
```
Replace `YOUR_BOT_TOKEN` with the token from **User Settings > Applications** in the Fluxer web/desktop app.
Keep bot tokens 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](https://github.com/twitter-archive/snowflake/tree/snowflake-2010) as IDs for users, messages, channels, and other entities.
Within a single entity type (for example, messages), Snowflakes are unique. Different entity types may share the same numeric Snowflake, so always track which entity 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. Treat them as opaque strings unless you 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.
```ts
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. 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 generate Snowflakes from timestamps to paginate by time:
```ts
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](https://en.wikipedia.org/wiki/ISO_8601) format in UTC. Parse them with standard libraries in your language of choice.
## Nullable & Optional Fields
To stay close to Discord's API docs, the Fluxer API uses 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 response fields (documented or not) are backwards-compatible. Your client should ignore fields it doesn't recognize.
Breaking changes will be announced in advance, with a migration period where old and new versions both work.
## HTTP API
### User Agent
When making HTTP requests, set a custom `User-Agent` header that identifies your application. Example:
```text
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 your request body.
### Rate Limits
Rate limits are reported via HTTP headers. If you exceed a limit, you'll receive `429 Too Many Requests`. For details, see the [Rate Limits](./rate-limits) documentation.
## Gateway API (WebSocket)
Fluxer's Gateway API lets you maintain a long-lived WebSocket connection for real-time events. For how to connect and interact, see the [Gateway API](./gateway) 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
```text
https://fluxerusercontent.com
```
All 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 |
| Guild Embed Splash | `/embed-splashes/{guild_id}/{embed_splash_hash}.{ext}` | PNG, JPEG, WebP |
| 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. |
<Callout>
For attachment endpoints, if no transformations are specified (no `width`, `height`, `format`, or `quality` other than `lossless`), the original file is served directly.
</Callout>
### Examples
```text
# 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.mp4
```
## Static Assets CDN
### Base URL
```text
https://fluxerstatic.com
```
Default 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.
```ts
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.
```text
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
<Callout>
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.
</Callout>
### Multipart Form Data Upload
Upload files directly with your message using `multipart/form-data`:
```javascript
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 `PATCH`ing 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.
<Callout type="warning">
Only PNG, JPEG, WebP, and GIF image formats may be used at this time. Other file types are not supported.
</Callout>
```json
{
"embeds": [
{
"title": "Look at this image",
"image": {
"url": "attachment://cat.png"
}
}
]
}
```