> For the complete documentation index, see [llms.txt](https://docs.northscripts.dev/site/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.northscripts.dev/site/documentation/resources/bossmenu/developer-api.md).

# Developer API

### Server

```lua
local bossmenu = exports.north_bossmenu
```

`job` is always the job name, for example `'police'`. Exports return `false`, `0` or an empty table for a job that has no boss menu.

#### GetSocietyBalance

```lua
local balance = bossmenu:GetSocietyBalance(job)
```

Returns the society balance as a number. Alias: `GetBalance`.

#### AddSocietyMoney

```lua
local success = bossmenu:AddSocietyMoney(job, amount, reason)
```

Adds money to the society account and records it as income in the analytics.

| Parameter | Type             | Description                  |
| --------- | ---------------- | ---------------------------- |
| `job`     | string           | Job name                     |
| `amount`  | number           | Whole amount, greater than 0 |
| `reason`  | string, optional | Shown in the activity log    |

Returns `true` on success. Alias: `AddIncome`.

```lua
-- a mechanic repair script paying the shop
exports.north_bossmenu:AddSocietyMoney('mechanic', 750, 'Engine repair')
```

#### RemoveSocietyMoney

```lua
local success = bossmenu:RemoveSocietyMoney(job, amount, reason)
```

Removes money and records it as an expense. Returns `false` when the account does not hold enough. Alias: `AddExpense`.

```lua
if exports.north_bossmenu:RemoveSocietyMoney('mechanic', 1200, 'Parts order') then
    -- paid
end
```

#### HirePlayer

```lua
local success = bossmenu:HirePlayer(job, target, grade, acceptImmediately)
```

| Parameter           | Type              | Description                                                                                     |
| ------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| `job`               | string            | Job name                                                                                        |
| `target`            | number or string  | Server id or identifier of an online player                                                     |
| `grade`             | number or string  | Grade level or grade name                                                                       |
| `acceptImmediately` | boolean, optional | `true` sets the job at once. Otherwise the player receives the same offer prompt the menu sends |

Returns `true` when the offer was sent or the job was set.

#### FirePlayer

```lua
local success = bossmenu:FirePlayer(job, target)
```

`target` is a server id or an identifier. Works on offline players.

#### SetEmployeeGrade

```lua
local success = bossmenu:SetEmployeeGrade(job, target, grade)
```

`target` is a server id or an identifier, `grade` a level or a grade name. Works on offline players.

#### GetEmployees

```lua
local employees = bossmenu:GetEmployees(job)
```

Returns a list, online and offline employees together:

```lua
{
    {
        id = 12,                   -- server id when online, identifier when offline
        identifier = 'char1:abc…', -- ESX identifier or citizenid
        name = 'John Doe',
        role = 'sergeant',         -- grade name
        isOnDuty = true,
        dutyMinutes = 340,         -- last 7 days
        lastOnDuty = 'On duty',    -- display text
        avatar = 'data:image/…',   -- headshot, empty string when none
    },
}
```

#### GetEmployeeCount

```lua
local count = bossmenu:GetEmployeeCount(job)
```

#### GetJobGrades

```lua
local grades = bossmenu:GetJobGrades(job)
-- { { grade = 0, name = 'recruit', label = 'Recruit', salary = 200, isBoss = false }, ... }
```

Sorted from lowest to highest.

#### OpenBossMenu

```lua
local opened = bossmenu:OpenBossMenu(source)
```

Opens the menu for a player from the server. Returns `false` when the player may not open it.

#### IsBoss

```lua
local allowed = bossmenu:IsBoss(source)
```

`true` when the player is the boss of their job or their grade has **Boss Menu Access**.

### Client

```lua
exports.north_bossmenu:OpenMenu()     -- same checks as the placed point
exports.north_bossmenu:CloseMenu()
exports.north_bossmenu:IsMenuOpen()   -- boolean
```

Example, opening the menu from an item or a radial menu:

```lua
RegisterNetEvent('myscript:openBossMenu', function()
    exports.north_bossmenu:OpenMenu()
end)
```

***

## Overrides

`bridge/overrides.lua` connects your own scripts. It is not escrowed. Every function is optional: leave one commented out and the built-in is used.

### Client

| Function                                          | Replaces                                                                              |
| ------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `Bridge.Custom.Notify(opts)`                      | Notifications. `opts = { description, type }`, type is `success`, `error` or `inform` |
| `Bridge.Custom.ShowTextUI(text)` / `HideTextUI()` | The `[E]` prompt at a point                                                           |
| `Bridge.Custom.OpenStash(stashId, data)`          | Opening a stash. `data = { slots, weight, label }`. Return `true` when handled        |
| `Bridge.Custom.GetOutfit()`                       | Reading the clothing the player wears                                                 |
| `Bridge.Custom.ApplyOutfit(outfit)`               | Putting an outfit on and saving it                                                    |

Outfit format, for `GetOutfit` and `ApplyOutfit`:

```lua
{
    components = { { component_id = 11, drawable = 55, texture = 0 }, ... },
    props      = { { prop_id = 0, drawable = 46, texture = 0 }, ... },
}
```

### Server

| Function                                                                | Replaces                                                                                                                                                           |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Bridge.Custom.Bank`                                                    | Society money. A table with `GetBalance(job)`, `AddMoney(job, amount, reason)` and `RemoveMoney(job, amount, reason)`. `RemoveMoney` must return `true` on success |
| `Bridge.Custom.RegisterStash(stashId, label, slots, maxWeight, groups)` | Registering a stash with your inventory at start and when one is created. `groups = { [job] = 0 }`                                                                 |
| `Bridge.Custom.IsAdmin(source)`                                         | The admin check used by `/setbossmenu`. Return `true` or `false`                                                                                                   |
| `Bridge.Custom.Log(job, type, amount, actor, detail)`                   | Nothing by default. Called for every activity log entry, for Discord or your own logging                                                                           |

### Examples

A custom notification:

```lua
Bridge.Custom.Notify = function(opts)
    exports['my_notify']:Send(opts.description, opts.type)
end
```

An inventory that is not supported out of the box:

```lua
-- client block
Bridge.Custom.OpenStash = function(stashId, data)
    exports['my_inventory']:OpenStash(stashId, data.slots, data.weight)
    return true
end
```

A clothing resource that is not supported out of the box:

```lua
-- client block
Bridge.Custom.ApplyOutfit = function(outfit)
    local ped = PlayerPedId()
    for _, c in ipairs(outfit.components) do
        SetPedComponentVariation(ped, c.component_id, c.drawable, c.texture, 0)
    end
    for _, p in ipairs(outfit.props) do
        if p.drawable < 0 then
            ClearPedProp(ped, p.prop_id)
        else
            SetPedPropIndex(ped, p.prop_id, p.drawable, p.texture, true)
        end
    end
    exports['my_skin']:saveCurrentSkin()
end
```

Discord logs:

```lua
-- server block
local WEBHOOK = 'https://discord.com/api/webhooks/...'

Bridge.Custom.Log = function(job, type, amount, actor, detail)
    PerformHttpRequest(WEBHOOK, function() end, 'POST', json.encode({
        username = 'Boss Menu',
        embeds = { {
            title = ('%s — %s'):format(job, type),
            description = ('**Amount:** $%s\n**By:** %s\n**Detail:** %s')
                :format(amount, actor or 'script', detail or '-'),
        } },
    }), { ['Content-Type'] = 'application/json' })
end
```

`type` is one of `Deposit`, `Withdraw`, `Sale`, `Invoice`, `Hire`, `Fire`. `actor` is the identifier of the player who did it, or `nil` when the entry came from an export.

Your own banking:

```lua
-- server block
Bridge.Custom.Bank = {
    GetBalance  = function(job) return exports['my_bank']:getBalance(job) end,
    AddMoney    = function(job, amount, reason) return exports['my_bank']:add(job, amount, reason) end,
    RemoveMoney = function(job, amount, reason) return exports['my_bank']:remove(job, amount, reason) end,
}
```

***

## Database

Created automatically on first start. Nothing to import.

| Table                   | Holds                                                   |
| ----------------------- | ------------------------------------------------------- |
| `bossmenu_accounts`     | Society balances, only when no banking resource is used |
| `bossmenu_transactions` | Transaction and activity log behind the analytics       |
| `bossmenu_grade_perms`  | Permission set of each grade                            |
| `bossmenu_locations`    | Placed points                                           |
| `bossmenu_stashes`      | Stashes and the grades allowed to open them             |
| `bossmenu_wardrobes`    | Wardrobes                                               |
| `bossmenu_outfits`      | Saved outfits                                           |
| `bossmenu_settings`     | Business logo                                           |
| `bossmenu_avatars`      | Employee headshots                                      |

On ESX, `addon_account` and `addon_account_data` are created as well if they do not exist.
