The Private Server FiveM vote plugin lets you automatically reward players who vote for your server: in-game money, items, or any custom action through Lua hooks. It works with ESX, QBCore and Qbox, requires oxmysql and a FiveM server on build 9515 or later, and installs by extracting a folder into resources. Version 2.0 includes framework autodetection. Here is how to set it up step by step.
Key takeaways
- The sp-vote plugin detects Private Server votes every 30 seconds through the API and triggers the in-game reward, with no command for the player to type.
- Three officially supported frameworks: ESX, QBCore and Qbox. Autodetection via
Config.Framework = 'auto'avoids any manual configuration in 90% of cases. - The reward is set simply (
Config.Reward.Money) or through a custom Lua function (Config.Reward.Handler) to plug in any mechanic of your economy. - Two Lua events (
preVoteRewardandpostVoteReward) let you condition or trace each reward without touching the plugin's code.
Installation in 7 steps
The procedure takes about ten minutes on a server that is already set up. Allow more time if oxmysql or the RP framework aren't installed yet.
- Download the latest version of the plugin from the Private Server plugins page and extract the
sp-votefolder into your FiveM server'sresourcesfolder. - Install
oxmysqlif you haven't already, and configure its connection to your server's database. - Open
sp-vote/config.luaand choose the value ofConfig.Framework:'auto'for autodetection (recommended), or explicitly'esx','qbcore'or'qbox'. - Fill in
Config.Tokenwith the API token from your Private Server listing, available in your management area. Keep it private, don't share it with anyone, and don't commit it to a public repo. - Set
Config.Localeto'fr'or'en'depending on your community's language, andConfig.Reward.Moneyto the amount per vote (500 by default). - In
server.cfg, order theensurelines correctly:ensure oxmysql, then your framework (ensure es_extended,ensure qb-coreorensure qbx_core), thenensure sp-vote. - Restart the server. On first start, the plugin automatically creates the
sp_vote_rewardstable in your database. Check the logs to make sure no access error is reported.
No SQL file to import manually, no migration to run. The table is created and updated automatically at startup, as long as the SQL account has the CREATE and ALTER rights. The ZIP includes the player messages in French and English in the same package: the language is selected via Config.Locale, while the source code and console messages remain in English.
Our take
Don't test the plugin directly on your production server. Create a test FiveM instance with the same version, the same framework and a disposable database. A configuration error on
Config.Token, a Lua handler that crashes, or a misconfigured reward command can disrupt your server's economy or generate noisy logs in your framework. Once the mechanic is validated on the test server, switching to production takes five minutes.
How the player receives their reward
The player-side procedure is deliberately kept to a minimum. Here is what happens in practice.
- You send the player to your server's listing on Private Server and they vote by entering their FiveM username, the one displayed in game, not their RP character's name.
- The plugin queries our API every 30 seconds to retrieve the list of recent votes.
- As soon as a vote is identified as unprocessed, the plugin runs the reward logic: adding money, an item, a custom effect, depending on the configuration.
- If the player is in game at the time of the vote, the reward is granted immediately. If they are offline, it is queued and granted on their next login.
One point to communicate to your community: a username can be changed and isn't proof of identity. A player who changes their FiveM username between voting and logging in may not receive their reward, since the plugin looks for the exact username used when voting. A visible reminder on your listing or your Discord avoids recurring support tickets.
Customizing the reward: money, items or business logic
The default configuration gives a fixed amount of money for each vote. For most servers, that's enough. For those who want to go further, a custom Lua function takes over.
Simple configuration: fixed amount of money
Edit sp-vote/config.lua and set the value:
Config.Reward.Money = 500
This value is credited directly to the player's wallet, following the default logic of the detected framework. No Lua code to write.
Advanced configuration: custom Lua handler
For any more complex logic (paying into a bank account, adding an item, a conditional reward, a temporary boost), use Config.Reward.Handler. This function completely replaces Config.Reward.Money. Here are the official examples for each framework, paying 750 into the player's bank account.
ESX example:
Config.Reward.Handler = function(source, player, vote)
if not player.getAccount('bank') then
return false
end
return player.addAccountMoney('bank', 750, 'serveur-prive-vote') ~= false
end
QBCore example:
Config.Reward.Handler = function(source, player, vote)
return player.Functions.AddMoney('bank', 750, 'serveur-prive-vote') == true
end
Qbox example:
Config.Reward.Handler = function(source, player, vote)
return exports.qbx_core:AddMoney(source, 'bank', 750, 'serveur-prive-vote') == true
end
Choose only one example, the one that matches your framework, and place it in sp-vote/config.lua. No client-side change is needed.
The function's return value: what it really means
The plugin's behavior depends directly on what your handler returns. Three cases to know.
| Return | Plugin behavior | Use case |
|---|---|---|
| true | Vote marked as rewarded, no retry | Reward granted successfully |
| false | Automatic retry on the next pass (about 30 seconds) | Player temporarily unreachable or condition not met |
| Lua error or missing return | Vote blocked for manual review | Bug in the handler to fix before resuming |
For votes blocked for manual review, two console commands let you settle them after checking the payment:
sp_vote_resolve <voted_at> rewarded <username...>
sp_vote_resolve <voted_at> retry <username...>
The first marks the vote as rewarded with no retry. The second restarts the process on the plugin's next pass.
Our advice
Test your custom handler on a test account before deploying it. A classic mistake is returning
nilinstead oftrueafter a successful operation, which blocks the vote for manual review and needlessly fills your queue. A second common mistake: forgetting the case where the player hasn't yet loaded their bank account (ESX) at the time of the vote. Areturn falsein that case allows a natural retry as soon as the account is ready, with no intervention.
Lua events: customizing around the reward
Two events let you act before and after each reward, without touching the plugin's code.
preVoteReward: condition or cancel
The sp-vote:preVoteReward(playerSource, vote) event fires before the reward is granted. Calling CancelEvent() permanently cancels the reward for that vote, with no retry. Typical use cases: not rewarding a player in a parallel instance, filtering by their rank, applying a time-based rule.
postVoteReward: log or notify
The sp-vote:postVoteReward(playerSource, vote) event fires after a successful reward. Ideal for logging to your tracking system, sending a Discord notification, or triggering an in-game visual effect.
Complete server-side example
Here is an example that combines both events: cancellation outside instance 0, and logging of the rewards granted.
AddEventHandler('sp-vote:preVoteReward', function(playerSource, vote)
if GetPlayerRoutingBucket(playerSource) ~= 0 then
CancelEvent()
end
end)
AddEventHandler('sp-vote:postVoteReward', function(playerSource, vote)
print(('[sp-vote] Reward confirmed for %s (source %s, player %s, vote %s)'):format(
vote.username, tostring(playerSource), vote.player_identifier, vote.voted_at
))
end)
The vote payload contains three fields: username (the FiveM username used to vote), voted_at (the vote timestamp) and player_identifier (the character's persistent identifier, prefixed according to the framework). Be careful with playerSource in postVoteReward: it can be nil after a disconnection or a character change between the vote and the reward. Always check it before using it in a call that requires it. vote.player_identifier remains available in every case.
Handling pending votes and retention
The plugin automatically manages the votes' lifecycle with no manual intervention, following two simple rules.
Hourly cleanup. The plugin runs an automatic cleanup every hour. A paid or cancelled vote is deleted from the table only when both the vote AND its payment (or cancellation) are more than 7 days old. This retention leaves enough time to investigate a player dispute without overloading the database in the long run.
Keeping votes in progress. Votes waiting to be granted (player offline, active retry) and those blocked for manual review are kept indefinitely. There's no risk of losing a legitimate vote because of a player who hasn't logged in for 2 weeks: the reward is waiting for them in their next session.
Stuck or running into a problem? Our developers can help you integrate and configure the FiveM plugin. Open a ticket on our Discord, and we'll get back to you quickly.
Frequently Asked Questions
Is the plugin free?
Yes. The Private Server FiveM vote plugin is completely free to download and use. No feature is locked behind a subscription, there are no installation fees, and no limitations tied to your server's size or the number of votes processed.
Does it work with FiveM servers hosted at Oxygenserv, Minestrator or any other provider?
Yes, the plugin works on any FiveM hosting that accepts custom resources in the resources folder. There's no dependency on a specific host. Just check that your plan allows installing third-party resources and using oxmysql, which is the case for nearly all FiveM plans on the market.
What happens if the player votes with the wrong FiveM username?
The vote is counted on the Private Server side but no reward is granted in game, since the plugin can't find a player matching that username. The reward stays pending indefinitely until a player logs in with that exact username. Always tell your community to use their FiveM username as displayed in game, not their RP character name.
Can you give different rewards depending on the type of player (VIP, staff, beginner)?
Yes, via Config.Reward.Handler. The function receives the framework's player object, from which you can read any property (rank, job, VIP group, seniority) and adjust the amount or type of reward accordingly. It is one of the most common use cases of the custom handler.
Does the plugin handle server restarts during the reward process?
Yes. Votes are persisted in the database as soon as they are retrieved from the API. A server restart in the middle of processing loses no votes: on restart, the plugin picks up the list of unprocessed votes and continues the rewards.
Can you use the plugin without an RP framework (a classic PvP server)?
Not officially. The plugin needs ESX, QBCore or Qbox to work. A pure PvP FiveM server with no RP framework doesn't have the foundation the plugin expects. A partial workaround is possible by installing a minimal framework just for the plugin, but it isn't the recommended setup.
How do you check that the plugin is communicating properly with the Private Server API?
Check your FiveM server's logs after sp-vote starts. The plugin logs its connection status, its API calls and the rewards granted. A test vote from your Private Server listing (with a username present on the server) lets you validate the whole chain in under a minute. If the logs show no API call, first check the value of Config.Token and your server's outbound HTTPS access.


No comments yet.