F5 StudioF5 Studio
Skip to main content

Features

F5 Redeem Code turns a short string into instant, validated rewards. Every rule below is enforced server-side — the NUI only collects input.

Overview

FeatureSummary
Money rewardsPay out to one or several money accounts at once (cash, bank, crypto, black money…)
Item rewardsGrant up to maxItems distinct inventory items, each up to maxItemAmount
Reward typesmoney, item, or both
Public codesRedeemable by anyone, once per player
Private codesLocked to a list of target Citizen IDs (multi-target)
Usage limitOptional cap on total redemptions (max_uses, 0 = unlimited)
ExpiryOptional expiry date/time
One per playerEach Citizen ID can redeem a given code only once
CooldownPer-player debounce between attempts
Case-insensitivityOptional — SUMMER and summer treated as the same code
Inventory safetyItem rewards are refused (nothing granted) if the player can't carry them
Reusable namesDeleted codes free their name for re-creation

Rewards

A code's reward_type decides what it grants:

reward_typeGrants
moneyMoney only
itemItems only
bothMoney and items

Money (single or multi-account)

Money rewards are stored as a per-account list (moneys), so one code can pay, for example, $5000 bank and $250 crypto in a single redeem. Each entry targets a money type from F5Cfg.Money.types.

  • Only active money types (those with an account for the running framework) are accepted; unknown or inactive types are dropped.
  • Amounts are floored to whole numbers; entries ≤ 0 are dropped; duplicate types are summed.
  • The total across all accounts must not exceed F5Cfg.Rewards.maxMoney, or creation is rejected (admin_money_over_limit).
  • On redeem, each account is credited via the framework bridge. If a specific account credit fails it is logged and skipped; the others still apply.
Legacy single-amount codes

Older codes created before multi-account support stored a single money amount with no account list. On redeem these pay out to the configured F5Cfg.Money.payoutType account, and the admin console surfaces them on that account so an edit migrates them to the moneys format automatically.

Items

Item rewards are a list of { name, amount } pairs:

  • Up to F5Cfg.Rewards.maxItems distinct items per code (extras dropped).
  • Each amount is clamped to 1 … F5Cfg.Rewards.maxItemAmount.
  • Item names are resolved to their inventory label and icon for display in the panels and history.
  • Granting goes through the inventory bridge, so it works across ox / qb / qs / ps / codem / tgiann / ESX-native / custom.

Code scope: public & private

ScopeBehaviour
Public (is_private = 0)Any player may redeem it, subject to the usual once-per-player, expiry and usage-limit rules
Private (is_private = 1)Only players whose Citizen ID is in the code's target list may redeem it; everyone else gets redeem_private

Private codes support multiple targets — a list of Citizen IDs (target_citizenids), capped at F5Cfg.Codes.maxPrivateTargets. A single legacy target (target_citizenid) is still honoured for older codes.

Target validation (on create/edit)

When F5Cfg.Codes.validatePrivateTarget = true (default), targets are verified as the code is saved:

  1. Input Citizen IDs are sanitized, de-duplicated and capped at maxPrivateTargets.
  2. Online targets are confirmed instantly.
  3. Remaining targets are checked in one batched query against the framework's player table (players.citizenid for QB/QBox, users.identifier for ESX).
  4. If a target can't be found the save is rejected (admin_targets_not_found); if the DB can't be queried it fails closed (admin_target_unverifiable).

Set validatePrivateTarget = false to skip the DB check and trust the entered IDs. See Configuration → Codes.

Usage limits & expiry

RuleFieldBehaviour
Max usesmax_uses0 = unlimited. Otherwise, once total redemptions reach max_uses, further attempts return redeem_max_uses
One per playerEach Citizen ID may redeem a given code only once (redeem_already_used) — tracked in f5_code_redemptions
ExpiryexpiryOptional date/time. After it passes, attempts return redeem_expired. Leave empty for a code that never expires

Redeem validation

When a player submits a code, the server runs these checks in order and stops at the first failure:

#CheckFailure message (locale key)
1Per-player cooldown (cooldownMs)redeem_cooldown
2Non-empty coderedeem_empty
3Player has a valid Citizen IDredeem_error
4Code exists (and not deleted)redeem_invalid
5Not expiredredeem_expired
6Below max_usesredeem_max_uses
7Player allowed (public, or a private target)redeem_private
8Not already redeemed by this playerredeem_already_used
9Inventory has room for all itemsredeem_inventory_full
All passed → grant rewardsredeem_success
All-or-nothing items

The inventory-space check (step 9) runs before anything is granted. If any single item wouldn't fit, the whole redemption is refused and nothing is given — the player can free space and try again.

On success the server increments the code's use count, records the redemption (Citizen ID, name, Steam HEX, rewards, timestamp), optionally fires the code_redeem webhook, and returns the reward summary to the panel.

Case-insensitivity

With F5Cfg.Codes.caseInsensitive = true (default), code lookups and duplicate-name checks use LOWER(), so WELCOME2024 and welcome2024 are the same code. Set it to false for case-sensitive codes.

Reusable code names

Codes are soft-deleted — deleting sets a deleted flag rather than removing the row, preserving redemption history. A generated code_active column keeps the unique constraint only on live codes, so a deleted code's name becomes available again for a brand-new code. See Framework Compatibility → Database schema.

See Also