Resources

REC_Economy

Welcome to REC_Economy documentation.

See how much money actually exists on your server — cash, bank, black money, crypto — and what every society account is holding.

Category

PAIDESCROWED

Installation

Download the dependencies

GitHub - ox_lib

Download from here!!

Tebex - REC_ItemManager

Required when you count money items. Download from here!!

Download main resource

Tebex - REC_Economy

Download from here!!

Copy and paste this on your server.cfg

  # ox
  ensure ox_lib
  ensure oxmysql

  # RE:CORD
  ensure REC_Library
  ensure REC_Utils
  ensure REC_ItemManager
  ensure REC_Economy

Give yourself the ACE permission

  add_ace group.admin REC_Economy.command allow
  add_principal identifier.fivem:1 group.admin

Done

enjoy it !

REC_Economy waits for REC_ItemManager to finish loading before it aggregates, so it can add money items to the totals. Set config.ignore.moneyItems = true if you do not use money items and want to run without REC_ItemManager.

What it counts

SourceWhere it comes from
cash / bank_money / cryptoThe money column of the players table
black_money and other money itemsREC_ItemManager circulation × multiplier
Society balancesEvery job from your framework × its bank account

Only players who logged out within config.targetPlayerLastLoginDays days are counted, so abandoned characters do not inflate the totals.

Configuration

Register any item that should be treated as currency:

---@type table<string, REC_Economy.Server.Config.MoneyItem>
config.moneyItems = {

    ["black_money"] = {

        ---[[
        ---     Which currency this item counts as
        ---]]
        type = moneyTypes.black_money,

        ---[[
        ---     Value per item. 1 item counts as this much currency.
        ---]]
        multiplier = 1,
    },
}

Available types are cash, bank_money, black_money and crypto.

Admin UI

The panel can be opened in two ways. Both show the same build, but they are authenticated differently.

In-game (NUI)Browser
How to open/economyhttp://<host>:30120/REC_Economy/
AuthenticationACE groupAuthorization: Bearer <adminToken>
DefaultEnabledDisabled
Extra setupNoneSee below
The in-game UI works out of the box and never touches HTTP. If you only use /economy, you can skip the whole browser section.

The screen shows total money supply, a breakdown per currency with its share, and a searchable, sortable list of society balances. Re-aggregate rebuilds everything from the database and the bank.

config.web.aceGroups is a list — a player passes when they hold any one of them.

config.web = {

    ---@type string[]
    aceGroups = {
        "admin",
        -- "moderator",
    },
}

Browser route

This route is served on the same port your players connect to (30120 by default). That port has to stay open for players, so you cannot protect the panel by closing it — allowedAddresses (this machine only by default) and the token are all that stand between the panel and the internet.

Reach the panel from an address you have allowed. Any one of these works:

  • Reach it over a VPN (Tailscale, WireGuard)
  • Reach it through an SSH port forward
  • Put a TLS reverse proxy in front of it (see trustedProxies)
  • Only reach it from the same LAN

If you are on shared hosting and can do none of these, leave the browser route disabled and use the in-game UI.

Enabling it

config.web.http.enabled = true
  set REC_Economy:adminToken "a-random-string-of-32-chars-or-more"

48 characters, generated in your browser. Nothing is sent anywhere.

An empty token makes every /api/* call return 401. A token shorter than 32 characters prints a warning on startup. Give each RE:CORD resource its own token.

allowedAddresses

Requests from an address that is not on this list get 404 — before authentication, so the route stays invisible from the outside. The default allows this machine only.

allowedAddresses = {
    "127.0.0.0/8",        -- loopback
    "::1",
    -- "100.64.0.0/10",   -- Tailscale (CGNAT range)
    -- "192.168.1.0/24",  -- LAN
    -- "172.18.0.0/16",   -- Docker bridge
}

Entries are IPv4 CIDR blocks or literal addresses. IPv6 has no CIDR support, so write the address in lowercase canonical form. An entry that can never match is reported on startup.

Adding 0.0.0.0/0 publishes the panel to the entire internet, leaving the token as the only protection.

trustedProxies

Behind a reverse proxy every request arrives from the proxy itself, so the address check can no longer see the real client. Register the proxy instead:

trustedProxies = {
    "127.0.0.1",
}

Requests from a registered proxy skip the address check, which means access control becomes the proxy's job — configure authentication there (Caddy basic_auth, nginx allow / deny, Cloudflare Access). X-Forwarded-For is only written to the debug log, never used to authorise, because any client can forge it.

If you run a tunnel such as cloudflared or ngrok on the same host, every visitor arrives as 127.0.0.1. The default loopback entry then no longer means "this machine only" — add authentication at the tunnel.

Common setups

SetupConfigNotes
In-game onlyDefaultsNothing to configure
SSH port forwardenabled = true onlySource is loopback, already allowed
Tailscale / WireGuardAdd 100.64.0.0/10Or the single device address
Same LANAdd your LAN rangee.g. 192.168.1.0/24
Reverse proxy + HTTPStrustedProxies = { "127.0.0.1" }Authentication must be set on the proxy
The browser route speaks plain HTTP — FiveM cannot terminate TLS. The token travels unencrypted, so only use this route inside an encrypted path (VPN, SSH tunnel, or a TLS reverse proxy).

Endpoints

MethodPathAuth
GET/REC_Economy/api/moneysAddress check + token
POST/REC_Economy/api/refreshAddress check + token
GET/REC_Economy/locale.jsonAddress check only

While REC_Economy is still waiting for REC_ItemManager, the API answers 503 { "error": "not ready" }.

Command

CommandPermissionDescription
/economyconfig.web.aceGroupsOpens the admin UI in-game

Exports

getMoneys

Returns the aggregated amount of each currency, keyed by money type.

Takes no arguments. Returns table<MoneyTypes, MetaData>:

FieldTypeDescription
keyMoneyTypescash / bank_money / black_money / crypto
valueintegerTotal amount of that currency
exports.REC_Economy:getMoneys()

getSocieties

Returns every society account, keyed by society name.

Takes no arguments. Returns table<string, SocietyMetaData>:

FieldTypeDescription
namestringSociety name
labelstringDisplay label
typestring?Society type, when the bank provides one
moneyintegerAccount balance
exports.REC_Economy:getSocieties()
Both read the cache built at startup — no query runs per call. Press Re-aggregate in the UI to rebuild it. Money item circulation comes from REC_ItemManager's own cache, so recount there first if you need those numbers refreshed too.

Stracture

config/sv_config.lua
  ---@type REC_Economy.Shared.Enum
  local shEnums = require "@REC_Economy.shared.sh_enum"
  local moneyTypes = shEnums.moneyTypes

  ---@class REC_Economy.Server.Config
  local config = {}

  ---[[
  ---     Only count players who logged out within this many days
  ---]]
  ---@type integer
  config.targetPlayerLastLoginDays = 3

  ---[[
  ---     Ignore certain checks
  ---]]
  config.ignore = {

      ---@type boolean
      moneyItems = false,
  }

  ---[[
  ---     Items that should be counted as currency
  ---]]
  ---@type table<string, REC_Economy.Server.Config.MoneyItem>
  config.moneyItems = {

      -- ["black_money"] = {
      --     type = moneyTypes.black_money,
      --     multiplier = 1,
      -- },
  }

  ---[[
  ---     Admin UI
  ---     The in-game UI (/economy) is always available and is gated by aceGroups.
  ---     config.web.http below only affects the browser route.
  ---]]
  config.web = {

      ---@type string[]
      aceGroups = {
          "admin",
      },

      http = {

          ---@type boolean
          enabled = false,

          ---@type string
          token = GetConvar(GetCurrentResourceName() .. ":adminToken", ""),

          ---@type string
          distDir = "web/build",

          ---@type string[]
          allowedAddresses = {
              "127.0.0.0/8",
              "::1",
          },

          ---@type string[]
          trustedProxies = {
          },
      },
  }

  ---[[
  ---    Debug Mode
  ---]]
  ---@type boolean
  config.debugMode = true

  ---@class REC_Economy.Server.Config.MoneyItem
  ---@field type REC_Economy.Shared.Enum.MoneyTypes
  ---@field multiplier integer

  return config
©2026 RE:CORD Development Group. All rights reserved.