Instance
Discover a deployment’s endpoints, available features, and limits, look up the client’s approximate location, download its OpenAPI document, or choose how members of a new deployment sign in.
Get instance discovery is the entry point of the API. A client that knows only a Micup origin reads /.well-known/fluxer first, and that one unauthenticated response has every field of the instance discovery object. Those values include the API base URLs, the main Gateway WebSocket URL, and the Media Proxy base URL. They override the endpoint path defaults a deployment would otherwise serve from its canonical public origin.
Every route here is unauthenticated. A credential changes no response body. One that resolves to an account moves the rate limit bucket from the client IP address onto that account.
Each GET route answers with Access-Control-Allow-Origin: *, replaced by the request Origin when the deployment-wide cross-origin policy allows that origin. The Admin Instance API defines the operator side of the same configuration.
Instance discovery object
Section titled “Instance discovery object”The discovery document is the complete public description of one deployment. Every field without a ? is always present. This server never sends codename or age_policy, and domain_migration and endpoints.upload_relay are absent only from a server older than this version.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| codename? | string | The protocol generation the deployment speaks |
| api_code_version1 | integer | The version of the API server code this deployment runs |
| endpoints | instance endpoints object | Public service endpoints for this deployment |
| captcha | captcha configuration object | Public CAPTCHA configuration |
| features | instance features object | Public deployment feature state |
| gif | GIF provider object | The active GIF provider and its attribution requirement |
| sso | SSO status object | Public single sign-on state |
| registration | registration policy object | Public registration policy |
| community | community policy object | Community defaults and direct message policy |
| services | service availability object | Resolved third-party integration availability |
| limits | limit configuration object | Ordered limit rules and the trait names the deployment declares |
| push | push configuration object | Public Web Push identity |
| app_public | public application configuration object | Public client configuration |
| age_policy? | age policy object | Regional age policy for the deployment |
| domain_migration? | domain migration object | Web domain migration switch and logged-out rollout |
| username_migration? | username migration object | Username selection migration state and deadlines |
| username_tiers? | object | Mode of one-, two-, and three-character usernames, keyed 1, 2, and 3: locked, for_sale, or public |
1 The value is a plain integer that increases when the API introduces a change a client is expected to notice, and the current value is 1
Instance endpoints object
Section titled “Instance endpoints object”Each value is an absolute URL supplied by the operator. A value can be a bare origin or an origin with a path prefix, because a deployment can serve several roles from one canonical public origin. A client accepts two endpoints that share an origin and MUST NOT infer a separate host, scheme, or port for any of them.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| api1 | string | Base URL for authenticated API requests |
| api_client1 | string | Base URL for client API requests |
| api_public | string | Base URL for public API requests |
| gateway2 | string | The main Gateway WebSocket URL |
| media | string | Media Proxy base URL |
| upload_relay? | string | Attachment upload relay base URL |
| static_cdn3 | string | Static asset base URL |
| marketing | string | Marketing site base URL |
| admin | string | Admin application base URL |
| invite | string | Invite link base URL |
| gift | string | Gift link base URL |
| webapp | string | Web application base URL |
1 Both fields are the same configured client API endpoint, which the first-party web application reads. api_public is the separately configured public API endpoint, which a bot, a library, or any other third-party client reads. A deployment can point the two at one origin, and the instance Micup hosts does not
2 The value is the configured Gateway endpoint and its scheme is ws or wss as the operator configured it
3 When a deployment configures a separate static asset domain, the value is https:// followed by that domain, with no port
Every value is the exact origin the deployment advertises, including its scheme and any explicit port, and a deliberately plain HTTP deployment publishes http and ws values here.
The operator configures one canonical public origin with an exact http or https scheme, a host, and an optional explicit port. The web application is served at that origin itself, and the other endpoints default to a path under it:
| Endpoint | Default path |
|---|---|
| HTTP API | /api |
| Media Proxy | /media |
| Admin application | /admin |
| Marketing site | /marketing |
| Invite links | /invite |
| Gift links | /gift |
| Gateway | /gateway |
The Gateway scheme is ws or wss. A port that equals the default for its scheme is omitted.
A deployment can configure a separate static asset domain, invite domain, and gift domain, and it can replace any single endpoint with an exact override.
Example
Section titled “Example”{ "api": "https://micup.gg/api", "api_client": "https://micup.gg/api", "api_public": "https://micup.gg/api", "gateway": "wss://micup.gg/gateway", "media": "https://micup.gg/media", "static_cdn": "https://micup.gg", "marketing": "https://micup.gg/marketing", "admin": "https://micup.gg/admin", "invite": "https://micup.gg/invite", "gift": "https://micup.gg/gift", "webapp": "https://micup.gg"}CAPTCHA configuration object
Section titled “CAPTCHA configuration object”Whether this deployment asks for a CAPTCHA on gated operations.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| provider | string | The CAPTCHA provider in use |
CAPTCHA providers
Section titled “CAPTCHA providers”| Value | Description |
|---|---|
| altcha | An ALTCHA proof-of-work challenge gates the operations that require one |
| none | The deployment requires no CAPTCHA |
The complete challenge handshake, including the X-Captcha-Token request header, is defined in CAPTCHA handling.
Instance features object
Section titled “Instance features object”Deployment-wide switches a client reads before it offers a feature, plus whether the deployment calls itself self-hosted.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| voice_enabled | boolean | Whether voice and video calling is enabled |
| stripe_enabled2 | boolean | Whether premium purchases through Stripe billing are available |
| premium_enabled3 | boolean | Whether the deployment has a premium tier, so premium state, gifts and perks apply |
| stripe_serviceable4 | boolean | Whether existing Stripe subscriptions can be managed, cancelled and billed |
| self_hosted | boolean | Whether this deployment identifies itself as self-hosted |
| presigned_attachment_uploads | boolean | Whether a client can request presigned attachment upload URLs |
| emails_enabled1 | boolean | Whether the deployment sends email |
| premium_trial_days7 | integer | Length in days of the premium trial a new account can start, 0 when none is offered |
| gift_codes_enabled8 | boolean | Whether premium gift codes can be redeemed |
| phone_verification_enabled | boolean | Deprecated. Always false |
| account_identity5 | string | How members sign in, one of the account identity modes |
| tag_style6 | string | How usernames are tagged, one of the tag styles |
1 The value is true only when email is switched on and the transport is completely configured. It is always false on a username deployment
2 True only when billing is switched on, a Stripe secret key is set, at least one currency has both a monthly and a yearly price, and premium_enabled is true. It is computed on each request
3 Always true on a hosted deployment. A self-hosted deployment reports true only while its premium mode is mirror
4 On a hosted deployment, true while billing is switched on and a Stripe secret key is set. A self-hosted deployment reports true while a Stripe secret key is set and premium_enabled is true, even after billing is switched off
5 Always email on a hosted deployment. A client treats a missing value as email, which is what a deployment from before the field existed means
6 Always none on a username deployment. Always random on a hosted deployment and on an instance that existed before the field. A client treats a missing value as random
7 Above 0 only on a self-hosted deployment in premium mirror mode with the ALTCHA CAPTCHA check enabled and the trial email hash key configured
8 False only on a self-hosted deployment that gives premium to everyone
A deployment that reports emails_enabled as false sends no verification, password recovery, or IP authorisation message, and the flows that depend on one are unusable there. Deployment availability states which routes a self-hosted deployment does not serve at all.
Account identity modes
Section titled “Account identity modes”| Value | Description |
|---|---|
| Members register and sign in with an email address | |
| username | Members register and sign in with a username, and the deployment collects no email address |
Tag styles
Section titled “Tag styles”| Value | Description |
|---|---|
| none | Usernames are unique and shown without a tag. Every account that is not a bot has the discriminator 0000 |
| random | Every account gets a random tag. Tags are shown and can be changed |
A username deployment answers its email routes with 400 EMAIL_UNAVAILABLE_ON_INSTANCE. Authentication and Email and password changes list them. Routes that exist only for username sign-in, such as recover an account, answer 400 USERNAME_SIGN_IN_ONLY on an email deployment.
GIF provider object
Section titled “GIF provider object”The GIF provider this deployment has bound, and whether a client shows its attribution mark.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| provider | string | Stable machine name of the active GIF provider |
| display_name | string | Human-readable provider name a client shows |
| attribution_required1 | boolean | Whether a client shows the provider attribution |
1 A client that renders GIF results displays the provider’s attribution mark alongside them when this value is true
The fields describe the provider a deployment has bound even when service availability reports gif_enabled as false. A client reads gif_enabled to decide whether to offer the picker at all. A deployment that has bound no GIF provider still publishes the stock values klipy, Klipy, and false.
Registration policy object
Section titled “Registration policy object”Who can register an account on this deployment.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| mode | string | The registration mode |
| admin_registration_urls_enabled1 | boolean | Whether an administrator-issued registration URL code is accepted |
1 When true, Register an account accepts registration_url_code, a valid code admits registration even while mode is closed, and the code’s own approval requirement replaces the one the mode would set
Registration modes
Section titled “Registration modes”| Value | Description |
|---|---|
| open | Anyone can register and receives a session immediately |
| approval | Registration succeeds but the account waits for administrator approval before it can sign in |
| closed | Public registration is refused |
Community policy object
Section titled “Community policy object”Whether this deployment runs as one community, and whether direct messages exist on it at all.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| single_community | boolean | Whether this deployment runs as one community that every account joins |
| single_community_guild_id1 | ?snowflake | The ID of the guild every account joins in single-community mode, or null |
| direct_messages_disabled | boolean | Whether direct messages and friend requests are disabled for the whole deployment |
| guild_create_access | boolean | Whether every account can create communities, or only admins and holders of the feature_guild_create limit |
1 The identifier is published only while single_community is true and the deployment has designated a community guild
Service availability object
Section titled “Service availability object”Each field reports whether one optional integration is available on this deployment.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| gif_enabled | boolean | Whether the GIF picker is available |
| youtube_enabled | boolean | Whether YouTube link enrichment is available |
| bluesky_enabled | boolean | Whether Bluesky connections are available |
Push configuration object
Section titled “Push configuration object”This deployment’s public Web Push identity.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| public_vapid_key1 | ?string | The deployment’s Web Push VAPID public key, or null |
1 Null when the deployment has configured no Web Push identity
Limit configuration object
Section titled “Limit configuration object”The ordered rules a client evaluates to work out the limits that apply to an account or a guild.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| version | integer | The wire format version, always 2 |
| traitDefinitions1 | array[string] | The trait names this deployment declares |
| rules | array[limit rule object] | The rules to evaluate |
| defaultsHash2 | string | A hash of the release’s built-in default limit values |
1 A stock hosted configuration publishes the single name premium, which is computed from the account’s premium state
2 The value is computed from the release’s default limit values alone, so an operator editing a rule leaves it unchanged. It changes when a release changes the defaults, which invalidates a resolution a client cached against the older ones
Each rule publishes only the keys whose values differ from the release defaults. The defaults themselves are not published in this document, so a client MUST hold its own copy of them. Before it resolves anything, a client MUST also rebuild every rule into a full limit map, taking the default value of every limit key and overlaying that rule’s overrides on it.
The client starts from the default value of every key. It evaluates the rules from least specific to most specific, where specificity is the total number of trait and guild feature names in a rule’s filters. Two rules of equal specificity keep their published order. A rule matches when every trait it names is present in the evaluation context and every guild feature it names is present.
A rule that names no trait and no guild feature replaces the current value for each key it has. A rule that names at least one raises the current value to its own value when that is higher. Because a rebuilt rule has every key, an unfiltered rule returns each key it did not override to the default. A matching filtered rule raises each key it did not override to at least the default.
The evaluation contexts are listed below. A client reads the key’s scope and the rule’s filters to decide which keys an evaluation applies. The limit key registry states the scope of each key.
| Scope | User evaluation | Guild evaluation |
|---|---|---|
| user | Applied | Applied only when the rule has no guild feature filter |
| guild | Not applied | Applied when the rule has a guild feature filter, or when the rule has no trait filter at all |
| both | Applied | Applied |
Nothing validates a rule’s traits filter against traitDefinitions, so a rule can filter on a name that collection omits. A self-hosted deployment whose premium mode is everyone publishes an empty collection and has no rule that filters on premium.
Limit rule object
Section titled “Limit rule object”One rule of the limit configuration, with the filters that select it and the values it sets.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id | string | The stable rule identifier |
| filters? | limit filters object | The traits and guild features that select the rule, omitted when the rule always matches |
| overrides1 | map[string, integer] | Integer values keyed by limit key |
1 An entry whose value is negative or is not a finite number is ignored when the rule is applied
Example
Section titled “Example”{ "id": "premium", "filters": {"traits": ["premium"]}, "overrides": { "max_message_length": 4000, "max_guild_emojis": 250 }}Limit filters object
Section titled “Limit filters object”The traits and guild features a limit rule requires before it matches.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| traits? | array[string] | Trait names that must all be present for the rule to match |
| guildFeatures? | array[string] | Guild feature names that must all be present for the rule to match |
An empty or omitted collection imposes no condition. A rule whose filters object has neither collection always matches, and it replaces each key’s current value exactly as a rule that omits filters does.
Limit keys
Section titled “Limit keys”Each key names one limit. A key whose name begins with feature_ is a feature gate whose value is 0 when the feature is unavailable and 1 when it is available. Every other key’s value is a bound in the unit named by its description.
| Value | Description |
|---|---|
| avatar_max_size | Maximum file size for avatar uploads in bytes, in user scope |
| cross_channel_spam_block_after | Channels the same invite or link can reach in the short window before posts are refused; 0 is off, in user scope |
| cross_channel_spam_block_after_bot | The same block threshold for bots, counting invites only; 0 turns it off, in user scope |
| cross_channel_spam_freeze_after | Communities in the short window before a non-bot account trying the same link is frozen; 0 is off, in user scope |
| dm_duplicate_freeze_after | New conversations with the same text, invite or link before the account is frozen; 0 is off, in user scope |
| dm_open_alert_per_hour | New conversation attempts in an hour that file one admin alert, exempt accounts included; 0 is off, in user scope |
| emoji_max_size | Maximum file size for emoji uploads in bytes, in guild scope |
| feature_animated_avatar | Allow animated avatar uploads, in user scope |
| feature_animated_banner | Allow animated banner uploads, in user scope |
| feature_app_commands | Let the user see the command catalog, run commands, click third-party components and submit modals, in user scope |
| feature_bot_components | Let the bot write buttons and link buttons and receive clicks, in user scope |
| feature_bot_components_v2 | Let the bot send Components v2 messages; 0 by default until every client draws them, in user scope |
| feature_bot_interactions | Emergency switch for every bot: commands, delivery, callbacks, followups and components, in user scope |
| feature_bot_interactions_blocked | 1 stops everything feature_bot_interactions covers for one bot, set through a trait rule, in user scope |
| feature_bot_modals | Let the bot open modals, in user scope |
| feature_bot_select_menus | Let the bot write select menus and receive choices, in user scope |
| feature_custom_discriminator | Allow custom discriminator selection, in user scope. Ignored for people on an instance with the none tag style |
| feature_custom_notification_sounds | Allow custom notification sounds, in user scope |
| feature_early_access | Access to beta features, in user scope |
| feature_feed | Post to, read and interact with the feed; 0 closes every feed route and holds videos in processing, in user scope |
| feature_feed_categories | Show the feed categories; 0 closes their routes and ignores a new post’s category, in user scope |
| feature_feed_comment_like_notifications | Instance-wide: record comment_like notifications; 0 until clients that ignore unknown types have shipped, in user scope |
| feature_feed_discover | Read the Discover feed of popular public posts; 0 closes the route and empties the list, in user scope |
| feature_feed_discover_media | Instance-wide: let posts with images or video into Discover; stays 0 until media scanning is verified, in user scope |
| feature_feed_discover_video | Instance-wide: let public posts with a Bunny video into Discover; 0 until video scanning is verified, in user scope |
| feature_feed_reply_notifications | Instance-wide: record comment_reply notifications; 0 until clients that ignore unknown types have shipped, in user scope |
| feature_feed_suggestions | Suggest popular accounts and communities and allow following a suggested account; 0 closes both, in user scope |
| feature_feed_topics | Show the feed topics; 0 closes their routes and ignores a new post’s topic, in user scope |
| feature_feed_video | Post one video (up to 500 MB) through Bunny Stream; 0 until the Bunny token and scanning are live, in user scope |
| feature_feed_views | Instance-wide: count and show post views; 0 hides the counts and closes POST /feed/views, in user scope |
| feature_global_expressions | Use expressions across all guilds, in user scope |
| feature_guild_roster | Instance-wide: enable Micup Roster; 0 stops processing and settings writes, in user scope |
| feature_guild_create | Create communities while the instance restricts community creation, in user scope |
| feature_higher_video_quality | Access to higher video streaming quality, in user scope |
| feature_mature_content_settings | Offer mature content and content warning settings; 0 hides unset ones while stored values keep working, in user scope |
| feature_micupbot | Instance-wide: enable MicupBOT; 0 stops processing and settings writes, in user scope |
| feature_name_style | Set a name font and colour; 0 refuses setting one while removing stays allowed, in user scope |
| feature_per_guild_profiles | Different profile per guild, in user scope |
| feature_profile_theme | Paint the profile card with a two-colour gradient; 0 refuses setting one, in user scope |
| feature_role_gradient | Assign a second role colour, in guild scope |
| feature_role_icons | Assign Unicode or guild emoji role icons, in guild scope |
| feature_shop_boost_payriff | Sell the boost slot through Payriff; 0 hides it from Payriff buyers, Paddle never reads it, in user scope |
| feature_table_game_chance_rewards | Instance-wide: Micup Plus season rewards for okey and 101; 0 withholds them until legal review, in user scope |
| feature_table_game_ranked | Instance-wide: ranked table games, leaderboards and profile leagues; 0 stops them, stored ratings stay, in user scope |
| feature_voice_entrance_sounds | Play a sound when joining voice, in user scope |
| feed_fanout_max_followers | Most followers an author can have and still get new posts written to follower home feeds, in user scope |
| feed_fanout_max_posts_per_day | Posts per author per day written to follower home feeds; later posts show only on the profile, in user scope |
| feed_fanout_min_followers | Follower count an author read at request time must drop below to get home feed writes again, in user scope |
| feed_suggestions_min_followers | Instance-wide: fewest followers a suggested account needs; values below 1 count as 1, in user scope |
| max_attachment_file_size | Maximum size of each attachment file in bytes, in user and guild scope |
| max_attachments_per_message | Maximum number of file attachments per message, in user and guild scope |
| max_bio_length | Maximum characters in a user biography, in user scope |
| max_bookmarks | Maximum bookmarked messages, in user scope |
| max_boost_slots | Community boost slots an account holds without buying extra slots, in user scope |
| max_channels_per_category | Maximum channels per category, in guild scope |
| max_comments_per_post | Maximum comments one feed post can hold, in user scope |
| max_custom_backgrounds | Maximum custom profile backgrounds, in user scope |
| max_embeds_per_message | Maximum number of embeds per message, in user and guild scope |
| max_favorite_meme_tags | Maximum meme tags to track, in user scope |
| max_favorite_memes | Maximum favourited memes, in user scope |
| max_feed_posts_per_day | Maximum feed posts one account can publish in a day, in user scope |
| max_following | Maximum number of users one account can follow, in user scope |
| max_group_dm_recipients | Maximum members per group direct message, in user scope |
| max_group_dms_per_user | Maximum group direct messages a user can own, in user scope |
| max_guild_channels | Maximum channels per guild, in guild scope |
| max_guild_emojis | Maximum total emojis per guild, in guild scope |
| max_guild_emojis_animated1 | Compatibility alias for older clients, in guild scope |
| max_guild_emojis_animated_more1 | Compatibility alias for older clients, in guild scope |
| max_guild_emojis_static1 | Compatibility alias for older clients, in guild scope |
| max_guild_emojis_static_more1 | Compatibility alias for older clients, in guild scope |
| max_guild_invites | Maximum active invites per guild, in guild scope |
| max_guild_joins_per_day_new_account | Communities a new account can join by itself in a day; 0 is no limit, in user scope |
| max_guild_joins_per_hour_new_account | Communities a new account can join by itself in an hour; 0 is no limit, in user scope |
| max_guild_members | Maximum members per guild, in guild scope |
| max_guild_roles | Maximum roles per guild, in guild scope |
| max_guild_soundboard_sounds | Maximum soundboard sounds per guild, in guild scope |
| max_guild_stickers | Maximum stickers per guild, in guild scope |
| max_guild_stickers_more2 | Compatibility alias for older clients, in guild scope |
| max_guild_video_fps | Maximum screen sharing frame rate, in guild scope |
| max_guild_video_height | Maximum camera and screen sharing height in pixels, in guild scope |
| max_guilds | Maximum number of guilds a user can join, in user scope |
| max_message_length | Maximum number of characters per message, in user and guild scope |
| max_new_dms_per_day | New one to one conversations an established account can start in a day; 0 is no limit, in user scope |
| max_new_dms_per_day_bot | New one to one conversations a bot can start in a day; 0 is no limit, in user scope |
| max_new_dms_per_day_new_account | New one to one conversations a new account can start in a day; 0 is no limit, in user scope |
| max_new_dms_per_hour | New one to one conversations an established account can start in an hour; 0 is no limit, in user scope |
| max_new_dms_per_hour_bot | New one to one conversations a bot can start in an hour; 0 is no limit, in user scope |
| max_new_dms_per_hour_new_account | New one to one conversations a new account can start in an hour; 0 is no limit, in user scope |
| max_private_channels_per_user | Maximum direct message channels per user, in user scope |
| max_purchased_boost_slots | Bought boost slots an account may hold at once; a purchase past it is refused, in user scope |
| max_reactions_per_message | Maximum distinct reactions per message, in guild scope |
| max_relationships | Maximum friend and blocked relationships, in user scope |
| max_users_per_message_reaction | Maximum users who can use the same reaction on a message, in guild scope |
| max_voice_message_duration | Maximum voice message duration in seconds, in user and guild scope |
| max_webhooks_per_channel | Maximum webhooks per channel, in guild scope |
| max_webhooks_per_guild | Maximum webhooks per guild, in guild scope |
| new_account_age_hours | Accounts younger than this many hours use the new account conversation and join limits, in user scope |
| new_dm_captcha_after | New conversations in the short window after which each further one asks for a captcha; 0 is off, in user scope |
| spam_short_window_minutes | Window in minutes for the new conversation captcha and the cross channel counts, in user scope |
| sticker_max_size | Maximum file size for sticker uploads in bytes, in guild scope |
1 Emoji limits are enforced as one shared total against max_guild_emojis, and the aliases exist only for older clients. The default of each alias equals the max_guild_emojis default
2 Sticker limits are enforced as one shared total against max_guild_stickers
Where a rule sets max_guild_emojis, max_guild_stickers, or one of the compatibility aliases, it republishes that key in its own overrides even when the value matches the default.
Public application configuration object
Section titled “Public application configuration object”Branding, setup state, legal documents, registration fields, and the default client language a client reads before an account signs in.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| branding | public branding object | Public instance identity |
| setup | public setup state object | Initial configuration state |
| legal | public legal configuration object | Registration legal document URLs |
| registration | public registration fields object | Registration field collection policy |
| localization?1 | object | Default client language for visitors who have not chosen one |
1 The object has the nullable string default_locale, a client locale such as tr, and the string array default_locale_time_zones of IANA time zones. A visitor who has not chosen a language and whose time zone is listed opens in default_locale. Any other such visitor gets the first browser language the client supports, or default_locale when none is supported. A language the visitor saved, or the one stored in their account, always wins. While default_locale is null, or names a locale the client does not ship, the client detects the language as it would without this object
Public branding object
Section titled “Public branding object”The instance identity a client renders: its name, its images, its theme colour, its status page links, and the name of its premium tier. The image URLs customise browser metadata, install metadata, and link previews.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| product_name | string | The configured instance name a client displays |
| icon_url | ?string | Full application icon URL, or null |
| symbol_url | ?string | Compact application symbol URL, or null |
| logo_url | ?string | Application logo URL, or null |
| wordmark_url | ?string | Application wordmark URL, or null |
| favicon_url | ?string | Browser favicon URL, or null |
| theme_color | ?string | Browser theme colour, or null |
| status_page_url | ?string | Public status page URL, or null |
| status_page_incident_history_url | ?string | Status page incident history URL, or null |
| premium_product_name | string | Name of the premium tier a client displays. A self-hosted deployment reports Premium until the operator sets a name |
| premium_info_url | ?string | Absolute URL of a page describing the premium tier, or null |
Public setup state object
Section titled “Public setup state object”Whether the deployment has finished its initial configuration, and where an operator goes to continue it.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| configured | boolean | Whether initial deployment configuration is complete |
| admin_url1 | ?string | The admin application URL used to continue setup, or null |
| account_identity_locked? | boolean | Whether the sign-in method can no longer change, sent only while a self-hosted deployment is not configured |
1 The value is the deployment’s configured admin endpoint, and it is null when no admin endpoint is configured
account_identity_locked is true once the first account exists, and on a deployment stored as already in use. Set the setup sign-in method returns 409 there.
Public legal configuration object
Section titled “Public legal configuration object”The public URLs a client links from its registration form and settings.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| terms_url | ?string | Public terms of service URL, or null |
| privacy_url | ?string | Public privacy policy URL, or null |
| source_url | ?string | Public URL where the instance offers its corresponding source code, or null |
Public registration fields object
Section titled “Public registration fields object”Which extra fields public registration collects.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| collect_date_of_birth | boolean | Whether public registration collects and validates a date of birth |
Username migration object
Section titled “Username migration object”The public state of the instance username migration. Clients read it to decide whether to ask people without a selected username to choose one.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| state | string | legacy, preparing, or selecting |
| epoch | integer | Migration generation, 0 until the first preparation |
| preparing_at? | ?ISO8601 timestamp | When preparation began, or null |
| started_at | ?ISO8601 timestamp | When selection began, or null before selecting |
| forced_at | ?ISO8601 timestamp | The selection deadline, seven days after started_at, or null before selecting |
legacy keeps every account on its existing name and tag. After forced_at, a person without a selected username must choose one before the actions listed under the user object.
Domain migration object
Section titled “Domain migration object”The public part of the instance domain migration configuration. The official web client reads it before sign-in to decide whether its legacy origin forwards to the new one. Every instance publishes it, and only the official web client acts on it.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the migration runs at all |
| anonymous_rollout_basis_points | integer | Share of logged-out devices moved to the new origin, in basis points (0-10000) |
| rollout_salt | string | Salt of the sampling hash, shared by accounts and devices |
| standalone_forwarding | boolean | Whether installed desktop web apps forward to the new origin once their data has moved |
enabled is the instance-wide switch. While it is false, no client starts a migration and a client that already migrated stops forwarding from the legacy origin. No passkey update opens, and the passkey bridge keeps working for people already on a new origin.
A logged-out device draws its own random ID once and keeps it. The device moves when its bucket over that ID and rollout_salt falls below anonymous_rollout_basis_points. Signed-in accounts use the domain migration assignment instead.
While standalone_forwarding is false, an installed desktop web app moves its data and stays on the legacy origin. Browser tabs forward either way.
Age policy object
Section titled “Age policy object”The regions where the deployment gates access behind an age check or blocks it.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| geos | array[age policy region object] | Regions with an age policy |
Age policy region object
Section titled “Age policy region object”Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| country_code | string | The ISO 3166-1 alpha-2 country code |
| region_code | ?string | The ISO 3166-2 subdivision code, or null when the entry covers the whole country |
| action | string | restrict to require an age check, or block to refuse access |
| card_verification_available | boolean | Whether card age verification is available in the region |
Geolocation object
Section titled “Geolocation object”The approximate location Micup resolved for the request, together with the regions where mature content is gated behind an age check or is unavailable.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| countryCode1 2 | ?string | The detected ISO 3166-1 alpha-2 country code, or null |
| regionCode1 2 | ?string | The detected ISO 3166-2 subdivision code within the country, or null |
| latitude1 3 | ?string | The approximate latitude, or null |
| longitude1 3 | ?string | The approximate longitude, or null |
| ageRestrictedGeos | array[geo entry object] | Locations where mature content requires an age check |
| ageBlockedGeos | array[geo entry object] | Locations where mature content is unavailable |
1 All detected fields are null when the location is unknown. A known location can still omit the subdivision code or coordinates
2 The value is upper case
3 The value is a decimal string
The geo collections are fixed by the release, so they are identical in every response. A client resolves its own country and subdivision from the detected fields and then selects the matching entry itself.
Example
Section titled “Example”{ "countryCode": "GB", "regionCode": "ENG", "latitude": "51.5074", "longitude": "-0.1278", "ageRestrictedGeos": [{"countryCode": "US", "regionCode": "TX"}], "ageBlockedGeos": []}Geo entry object
Section titled “Geo entry object”A geo entry names a whole country when its regionCode is null and names one subdivision otherwise.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| countryCode | string | The ISO 3166-1 alpha-2 country code |
| regionCode | ?string | The ISO 3166-2 subdivision code within the country, or null when the entry covers the whole country |
Account identity object
Section titled “Account identity object”The sign-in method a new deployment uses after set the setup sign-in method.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| mode | string | The account identity mode now in effect |
| tag_style | string | How usernames are tagged, one of the tag styles |
Bot catalog object
Section titled “Bot catalog object”The bots a client lists on its Bot System page, in two sections. The body is the same for every caller.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| micup1 | array[bot catalog card object] | Up to 22 bots made and run by Micup |
| community2 | array[bot catalog card object] | Up to 100 community bots made and run by independent developers |
1 The same applications, in the same order and with the same invite permissions, as features.official_apps in instance discovery: MicupBOT and Micup Roster first, each while its own feature is enabled, then the operator’s list. An operator-listed app appears only while it is public and has a bot user
2 In the operator’s order. A community bot appears only while its application is public, has a bot user, and that bot user has the verified flag and is not deleted, disabled, or banned. An application on both lists appears only in micup. The section is empty while eligibility cannot be checked
Eligibility is rechecked at least every 30 seconds, so a bot made private, deleted, unverified, disabled, or banned leaves the catalog within about 35 seconds. An entry whose application cannot be read is left out. A community card never carries Micup’s endorsement: a client labels it as a community bot and states that its developer is responsible for it.
Bot catalog card object
Section titled “Bot catalog card object”One bot in the bot catalog.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the bot’s application |
| name | string | The application name |
| icon | ?string | Avatar hash of the bot user, or null when it has none |
| description | ?string | Bio of the bot user, or null when it has none |
| invite_permissions | string | Decimal permission string to preselect when inviting the bot |
Get instance discovery
Section titled “Get instance discovery”GET/.well-known/fluxerReturns the instance discovery object describing this deployment.
The path has no /v1 prefix.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | instance discovery object | The discovery document was returned |
Rate limit
Section titled “Rate limit”60 requests per minute for each authenticated user, or for each client IP address when the request has no credential, on the instance:info bucket. Get OpenAPI document shares this bucket.
Get bot catalog
Section titled “Get bot catalog”GET/v1/instance/bot-catalogReturns the bot catalog object.
The catalog is built from memory that each API process refreshes in the background, so a request reads no application or user.
Request headers
Section titled “Request headers”| Field | Type | Description |
|---|---|---|
| If-None-Match? | string | An ETag from an earlier response to this route |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | bot catalog object | The catalog was returned |
| 304 | empty | The request sent a matching If-None-Match |
| 429 | rate limit response | Route or global bucket denies the request |
Response headers
Section titled “Response headers”| Field | Type | Description |
|---|---|---|
| ETag | string | A strong tag over the response body, sent on 200 and on 304 |
| Cache-Control | string | The literal value public, no-cache |
The ETag changes when the catalog changes. Treat it as an opaque value. no-cache makes a client revalidate on every read, so a page opened after a change shows the new catalog.
Rate limit
Section titled “Rate limit”60 requests per minute for each authenticated user, or for each client IP address when the request has no credential, on the instance:bot_catalog bucket.
Get client geolocation
Section titled “Get client geolocation”GET/v1/ipReturns the geolocation object for the request’s client address.
A lookup that resolves nothing still returns 200 with countryCode, regionCode, latitude, and longitude all null. Treat this as an unknown location.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | geolocation object | The location was resolved, fully, partly, or not at all |
Rate limit
Section titled “Rate limit”30 requests per minute for each authenticated user, or for each client IP address when the request has no credential, on the ip:geo_lookup bucket.
Set the setup sign-in method
Section titled “Set the setup sign-in method”PUT/v1/instance/setup/account-identityChooses how members sign in on a new self-hosted deployment, and on an email deployment whether usernames have tags. Returns an account identity object with the choice now in effect.
The setup wizard calls this before the owner account exists. The choice stays open on a self-hosted deployment until setup is complete or the first account exists. After that, on a deployment that was already in use before username sign-in existed, and on every hosted deployment, the route returns 409 ACCOUNT_IDENTITY_LOCKED. The choice and the first registration take turns, so a choice never lands after the first account exists. A repeated call while the choice is open replaces the earlier one.
JSON body
Section titled “JSON body”| Field | Type | Description |
|---|---|---|
| mode | string | The account identity mode to use |
| tag_style?1 | string | How usernames are tagged, one of the tag styles. Defaults to none |
1 A username instance always uses none. Sending random with username returns the field code TAG_STYLE_REQUIRES_EMAIL_SIGN_IN on tag_style
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | account identity object | The mode was stored |
| 400 | error response | The body is invalid, or random tags were requested with username |
| 409 | error response | ACCOUNT_IDENTITY_LOCKED, because the sign-in method can no longer change |
| 423 | error response | GENERAL_ERROR, because a registration or another choice held the turn for more than 15 seconds |
| 429 | rate limit response | Route or global bucket denies the request |
Side effects
Section titled “Side effects”The deployment stores the choice, and instance discovery reports it as account_identity and tag_style from then on. No Gateway Dispatch is emitted.
Rate limit
Section titled “Rate limit”10 requests per minute for each authenticated user, or for each client IP address when the request has no credential, on the instance:setup:account_identity bucket.
Get OpenAPI document
Section titled “Get OpenAPI document”GET/v1/openapi.jsonReturns the deployment’s OpenAPI 3.1 document as JSON with Content-Type: application/json; charset=utf-8.
The document has no ETag. Its server URL is the deployment’s api_client endpoint followed by /v1. Every path is relative to that URL.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | OpenAPI 3.1 document | The document was returned |
Rate limit
Section titled “Rate limit”60 requests per minute for each authenticated user, or for each client IP address when the request has no credential, on the instance:info bucket. The allowance is shared with Get instance discovery.