Experiments
An experiment is an instance-wide rollout that an operator configures. For each account, FiveCord works out from that configuration whether the account is in the rollout and which settings the account receives. The single route on this page resolves every experiment the server defines and returns them in one envelope, together with the polling cadence they share. This server defines voice_noise_suppression, whose placement protocol Voice defines, and domain_migration.
Every assignment is advice. A client that ignores one behaves as it does with the rollout off, and no route and no Gateway event reports what a client actually ran.
Experiment assignments object
Section titled “Experiment assignments object”One resolution of every defined experiment against one account. Every field is present on every response.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| poll_interval_seconds | integer | Seconds to wait before revalidating, from 60 through 86400 |
| poll_jitter_percent | integer | The largest random offset added to or subtracted from the wait, as a percentage of the wait, from 0 through 50 |
| assignments | assignment map object | One entry for each experiment the server defines |
Every account on the instance receives the same poll_interval_seconds and poll_jitter_percent. One request refreshes every experiment.
Assignment map object
Section titled “Assignment map object”One entry per experiment. The envelope reports this object even when it is empty.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| voice_noise_suppression? | noise suppression assignment object | The caller’s noise suppression assignment |
| domain_migration? | domain migration assignment object | The caller’s web domain migration assignment |
Ignore unknown experiments and treat a missing experiment as off.
This server version writes voice_noise_suppression on every response, including while a rollout is disabled. The disabled value is the first resolution outcome below, which reports enabled false and the stored config_version, so a client that compares config_version with the value from its previous response can see that an operator saved the configuration, even while the rollout stays disabled, and needs no second request for it.
Noise suppression backends
Section titled “Noise suppression backends”Noise suppression runs in the client, on the microphone track, before that track is published. FiveCord processes no audio for it. The registry is closed, and a backend outside it is not a value this API produces or accepts.
| Value | Description |
|---|---|
| none | No processing |
| standard | The browser or platform suppressor the client already has |
| gate | A noise gate keyed on input level |
| speex | The Speex preprocessor |
| rnnoise | The RNNoise recurrent model |
| gtcrn | The GTCRN model |
| deep_filter | The DeepFilterNet model |
A client MUST treat a backend absent from enabled_backends as unavailable, including one named by backend or by a guild override.
Noise suppression assignment object
Section titled “Noise suppression assignment object”One resolution of the instance noise suppression rollout against one account. Every field is present whenever the key is written.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the rollout is running on this instance |
| config_version | integer | The revision of the instance configuration this assignment was resolved from |
| user_targeted | boolean | Whether the caller is inside the rollout |
| backend | ?string | The backend the caller applies, and null where the caller is not targeted |
| source | ?string | Which rule targeted the caller, one of user_rule or canary, and null where the caller is not targeted |
| guild_overrides | array[guild override object] | Per-guild backend replacements that apply to the caller |
| enabled_backends | array[string] | The backends the client MAY run |
| allow_user_override | boolean | Whether the account’s own stored choice replaces backend |
| suppression_strength | integer | Suppression strength from 0 through 100, which only a backend that reads it applies |
config_version identifies the configuration revision. It can change without changing the caller’s assignment.
Resolution outcomes
Section titled “Resolution outcomes”The outcomes below set user_targeted to false, and they differ in what else they report.
- The rollout is off.
enabledis false,enabled_backendsandguild_overridesare empty, andallow_user_overrideis false. - The operator has excluded the caller.
enabledis true, and every other field is as in the first outcome. - The caller was not drawn.
enabledis true, andenabled_backends,guild_overrides, andallow_user_overrideall hold their configured values.
A caller is drawn either by the operator’s allowlist, which sets source to user_rule, or by the sampled share of the account population, which sets source to canary. A caller that is drawn while backend is absent from enabled_backends is reported as not drawn, with user_targeted false and both backend and source null.
A client branches on user_targeted rather than on enabled_backends, because the third outcome keeps the array populated. A guild_overrides entry applies in its guild whether or not the caller was drawn.
config_version reports the stored revision in all outcomes, the rollout being off included.
Noise suppression guild override object
Section titled “Noise suppression guild override object”One backend replacement scoped to one guild. While the caller is connected to a voice channel of that guild, the override’s backend replaces the assignment’s backend.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The guild the replacement applies in |
| backend | string | The backend to run in that guild |
An override naming a backend that is absent from enabled_backends is dropped before the response is written, so every entry is runnable.
Domain migration assignment object
Section titled “Domain migration assignment object”One resolution of the instance web domain migration rollout against one account. This server version writes the key on every response.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the caller’s web client moves to the new web origin |
A caller is drawn either by the operator’s allowlist or by the sampled share of the account population. enabled is false in every other case, the rollout being off included.
Only the official web client acts on this assignment, and only on its legacy origins. Every other client ignores it. The logged-out share and the instance-wide switch are published in the instance discovery document instead, because a client that holds no credential cannot read this route.
Get experiment assignments
Section titled “Get experiment assignments”GET/v1/experimentsResolves every defined experiment for the caller and returns an experiment assignments object. The response is derived per account, so it is never shared between accounts.
Response body
Section titled “Response body”Experiment assignments object.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | The envelope was resolved |
| 304 | empty | The request sent a matching If-None-Match |
Request headers
Section titled “Request headers”| Field | Type | Description |
|---|---|---|
| If-None-Match? | string | An ETag from an earlier response to this route |
A client sends the ETag it last received. FiveCord compares it against the tag of the envelope it just resolved and answers 304 with no body on a match. * matches any current tag. A weak comparison is used, so a W/ prefix on either side does not defeat the match.
Response headers
Section titled “Response headers”| Field | Type | Description |
|---|---|---|
| ETag | string | A strong tag over the envelope body, sent on 200 and on 304 |
| Cache-Control | string | The literal value private, no-cache |
| Vary | string | The literal value Authorization, replaced by Origin where the cross-origin policy echoed an allowed origin |
The ETag changes when the response changes. Treat it as an opaque value.
ETag is listed in Access-Control-Expose-Headers and If-None-Match in Access-Control-Allow-Headers, so a cross-origin client reads the tag and revalidates with it.
Polling
Section titled “Polling”A client reads this route once per session and then again every poll_interval_seconds, offset by a random amount up to poll_jitter_percent of that interval in either direction. It sends the last ETag on every request after the first. A client MUST NOT poll faster than the lower end of that jitter range.
Until the first successful response, use 300 seconds with 15 percent jitter.
Rate limit
Section titled “Rate limit”60 requests per 10 seconds for each authenticated user, on the default bucket.