> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nonefivem.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Server Exports

> Server-side exports for reading feature flags

Server reads are **asynchronous**: they resolve from memory when the configuration is current, and fetch when it is not.

Reads see every flag by default, because the server is the trusted side. Pass `'shared'` as the last argument to read as a client would.

## Exports

<Accordion title="IsFlagEnabled">
  Checks whether a boolean flag is on.

  ```lua theme={null}
  if exports.nocloud:IsFlagEnabled('new-hud', false) then
      -- ...
  end

  -- Read as a client would
  local shared = exports.nocloud:IsFlagEnabled('new-hud', false, 'shared')
  ```

  **Parameters**

  * key: `string` — The flag's key
  * fallback: `boolean` — Returned when the flag is not a readable boolean flag (optional, `false` by default)
  * runtime: `'server'|'shared'` — The runtime reading the flag (optional, `'server'` by default)

  **Returns**

  * enabled: `boolean` — Whether the flag is on

  A missing flag, one holding a non-boolean value, or one this runtime may not read all return the fallback — so archiving a flag in the dashboard can never break a running server.
</Accordion>

<Accordion title="GetFlagValue">
  Reads a flag's value, whatever its type.

  ```lua theme={null}
  local maxPlayers = exports.nocloud:GetFlagValue('max-players', 32)
  local motd = exports.nocloud:GetFlagValue('motd', 'Welcome')
  local economy = exports.nocloud:GetFlagValue('economy')

  if economy then
      print(economy.payMultiplier)
  end
  ```

  **Parameters**

  * key: `string` — The flag's key
  * fallback: `any` — Returned when the flag is missing or unreadable (optional)
  * runtime: `'server'|'shared'` — The runtime reading the flag (optional, `'server'` by default)

  **Returns**

  * value: `any` — The flag's value, or the fallback
</Accordion>

<Accordion title="GetFlag">
  Reads a flag whole — its key, type, value and runtime.

  ```lua theme={null}
  local flag = exports.nocloud:GetFlag('max-players')

  if flag then
      print(flag.key, flag.type, flag.value, flag.runtime)
  end
  ```

  **Parameters**

  * key: `string` — The flag's key
  * runtime: `'server'|'shared'` — The runtime reading the flag (optional, `'server'` by default)

  **Returns**

  * flag: `table?` — A table with `key`, `type`, `value` and `runtime`, or `nil` if the flag does not exist or this runtime may not read it
</Accordion>

<Accordion title="GetFlags">
  Reads every flag this runtime may see, keyed by flag key.

  ```lua theme={null}
  -- Every flag the server holds, server-only ones included
  local all = exports.nocloud:GetFlags()

  -- Exactly what clients are given
  local shared = exports.nocloud:GetFlags('shared')

  for key, value in pairs(all) do
      print(key, json.encode(value))
  end
  ```

  **Parameters**

  * runtime: `'server'|'shared'` — The runtime reading the flags (optional, `'server'` by default)

  **Returns**

  * values: `table` — The flag values, keyed by flag key
</Accordion>

<Accordion title="GetCachedFlags">
  Reads the values held right now, without contacting the API.

  ```lua theme={null}
  local cached = exports.nocloud:GetCachedFlags()
  ```

  **Parameters**

  * runtime: `'server'|'shared'` — The runtime reading the flags (optional, `'server'` by default)

  **Returns**

  * values: `table` — The flag values held in memory, keyed by flag key

  <Note>
    Unlike the other server reads, this one returns immediately rather than a
    promise. It is for callers that cannot wait — what it returns is whatever the
    last fetch or the stored cache left behind.
  </Note>
</Accordion>

<Accordion title="RefreshFlags">
  Refetches the flags now, ignoring both the cache window and the polling schedule.

  ```lua theme={null}
  local values = exports.nocloud:RefreshFlags()
  ```

  **Returns**

  * values: `table` — The flags the server now holds, server-only ones included

  **Throws**

  * If the API request fails, or if feature flags are disabled in the configuration.

  <Tip>
    This restarts the cache window like any other fetch, so the poll that follows
    an explicit refresh does not immediately spend another request.
  </Tip>
</Accordion>

<Accordion title="AreFlagsReady">
  Whether there are values to read.

  ```lua theme={null}
  if exports.nocloud:AreFlagsReady() then
      -- ...
  end
  ```

  **Returns**

  * ready: `boolean`

  False only before the first fetch answers with no cached snapshot to fall back on.
</Accordion>

<Accordion title="AreFlagsStale">
  Whether the values being served came from the last-known cache rather than from a fetch.

  ```lua theme={null}
  if exports.nocloud:AreFlagsStale() then
      print('Serving cached flags — the API has not answered yet')
  end
  ```

  **Returns**

  * stale: `boolean`

  True on a restart until the first read or poll answers, and for as long as the API stays unreachable after that.
</Accordion>

## Events

### nocloud.flags.updated

Fired locally on the server when a fetch finds a change. Values never cross the network as an event — this is a server-side listener, so it sees the whole snapshot including server-only flags.

```lua theme={null}
AddEventHandler('nocloud.flags.updated', function(values, changes)
    for _, change in ipairs(changes) do
        print(change.key, change.kind, json.encode(change.current))
    end
end)
```

**Handler parameters**

* values: `table` — Every flag the server holds, keyed by flag key
* changes: `table[]` — What differs from the previous snapshot

**Change entry**

| Field      | Type                                            | Description                                    |
| ---------- | ----------------------------------------------- | ---------------------------------------------- |
| `key`      | `string`                                        | The flag's key                                 |
| `kind`     | `'added'`, `'updated'` or `'removed'`           | How it differs from before                     |
| `type`     | `'boolean'`, `'string'`, `'number'` or `'json'` | The kind of value the flag holds               |
| `runtime`  | `'server'` or `'shared'`                        | The flag's runtime as of the newer snapshot    |
| `previous` | `any`                                           | The value before the change, `nil` when added  |
| `current`  | `any`                                           | The value after the change, `nil` when removed |

<Warning>
  A change nobody reads is a change nothing goes and finds. If this handler is
  the only thing watching your flags, set `flags.polling.enabled` to `true` in
  the [configuration](/cloud/sdks/cfx/configuration#feature-flags) — otherwise
  polling runs only while a client is reading.
</Warning>

A runtime flip counts as a change as much as a value does — it decides whether players still see the flag at all.

## Lua Library

For a cleaner API, include the server Lua library in your `fxmanifest.lua`:

```lua theme={null}
server_script '@nocloud/lib/server.lua'
```

**Usage**

```lua theme={null}
-- Boolean flag
if Cloud.flags:is_enabled('new-hud', false) then
    -- ...
end

-- Any value
local maxPlayers = Cloud.flags:get_value('max-players', 32)

-- A flag whole
local flag = Cloud.flags:get('max-players')

-- Every flag, keyed by flag key
local all = Cloud.flags:get_all()

-- Exactly what clients are given
local shared = Cloud.flags:get_all('shared')

-- Held values, no request, returns immediately
local cached = Cloud.flags:get_cached()

-- Refetch now
local values = Cloud.flags:refresh()

-- State
local ready = Cloud.flags:is_ready()
local stale = Cloud.flags:is_stale()
```

The library ships full LuaLS annotations, so `Cloud.flags` autocompletes with parameter and return types in any editor with the Lua Language Server.
