Examples β
Each example is one job. Copy the block, swap the ids, and wire it into your resource.
Related: API Β· Statebags Β· Events Β· Hooks
1. Register a society for your shop β
Scenario: You run a shop script. Valentine General Store should be its own organization with its own account and members.
Goal: Create that organization on server boot and look it up later β without saving a society id in your database.
-- server β run once when bln_society is ready
AddEventHandler('bln_society:ready', function()
exports.bln_society:EnsureSociety({
name = 'Valentine General Store',
preset = 'business',
fundingSource = Const.FUNDING.ACCOUNT,
ownerResource = 'my_store', -- your resource name
externalKey = 'valentine_general_store', -- your config id for this shop
})
end)
-- server β call this anywhere you need the shop's society
local function getStoreSociety(storeId)
return exports.bln_society:SocietyByKey('my_store', storeId)
endResult: First boot creates the society. Every boot after that finds the same one. getStoreSociety('valentine_general_store') gives you a handle β or nil if the society was deleted.
2. Send customer payment to the society account β
Scenario: A player buys items at your shop. The money should go into the shop's society till, not disappear.
Goal: Credit the society balance when a sale completes. No permission check β the buyer is a customer, not a member.
-- server β inside your purchase handler, after the player paid
RegisterNetEvent('my_store:purchaseComplete', function(storeId, transactionId, price)
local society = exports.bln_society:SocietyByKey('my_store', storeId)
if not society then return end
society:AddMoney(price, {
currency = 0,
type = 'sale',
reason = 'Cart sold',
ref = ('my_store:sale:%s'):format(transactionId), -- unique β safe to retry
})
end)Result: The society balance goes up. The ledger records the sale. Calling again with the same ref does not double-credit.
Member restocking from the till is different β use
Withdraw/Depositso permissions and player pockets are handled. See API β Finance.
3. Block staff actions for players without permission β
Scenario: A player tries to open your restock menu. Only store staff with the right permission should get in.
Goal: Check permission before your action runs. Reject everyone else.
-- server β before opening restock or running any staff-only logic
RegisterNetEvent('my_store:tryRestock', function(storeId)
local society = exports.bln_society:SocietyByKey('my_store', storeId)
if not society then return end
local charId = exports.bln_society:GetCharacterId(source)
if not charId then return end
if not society:HasPermission(charId, 'stores.restock') then
-- notify player: no permission
return
end
-- player passed β run your restock logic here
TriggerClientEvent('my_store:openRestockUi', source, storeId)
end)Result: Only members whose rank (or overrides) include stores.restock reach the restock UI. Everyone else is stopped here.
Register stores.restock in config/permissions.cfg.lua if it is not in the built-in list. Check permission names, not rank names like "Deputy".
4. Open the management menu from your own NPC β
Scenario: Your shop already has a clerk NPC. You do not want a second BLN Society prompt on the same counter β you want your interaction to open the society menu.
Goal: Open the BLN Society management UI when the player talks to your NPC.
-- server β triggered by your existing clerk / target / prompt
RegisterNetEvent('my_store:clerkTalk', function(storeId)
local society = exports.bln_society:SocietyByKey('my_store', storeId)
if not society then return end
society:Open(source) -- opens the management menu for this player
end)Result: The player sees the full society menu (members, finances, duty, etc.) without BLN Society placing its own world point.
Alternative β BLN Society draws the blip and prompt β
Use this only when you have no clerk or interaction of your own:
local society = exports.bln_society:SocietyByKey('my_store', storeId)
if not society then return end
society:SetPoint({
coords = { x = -324.1, y = 776.5, z = 117.8, h = 90.0 },
blip = { sprite = 'blip_shop_store', name = 'Valentine Store' },
})Members see the blip and prompt at the coords. Strangers do not.
5. On the client: show a staff door only when on duty β
Scenario: Your shop MLO has a back room. Only employees who are clocked in should see the enter prompt.
Goal: Read the local player's duty statebag and show or hide your prompt. No server callback.
-- client
local STORE_SOCIETY_ID = 3 -- send this from your server payload when the player enters the shop
CreateThread(function()
while not GlobalState['society:ready'] do Wait(100) end
while true do
local duty = LocalPlayer.state['society:duty']
local onDutyForThisStore = duty and duty.id == STORE_SOCIETY_ID
if onDutyForThisStore then
ShowBackRoomPrompt() -- your prompt / target / text UI
else
HideBackRoomPrompt()
end
Wait(500)
end
end)Result: The prompt appears only while the player is on duty for that society. Clock out and it disappears.
Your server already knows the society id β include it when the client loads the shop:
-- server β in whatever payload you send when the player enters the store
TriggerClientEvent('my_store:enter', source, {
storeId = storeId,
societyId = society and society.id or nil,
})For permission checks on the client, read LocalPlayer.state['society:memberships']. Bag shapes: Statebags. To refresh UI when duty changes without polling, use Events.
