> For the complete documentation index, see [llms.txt](https://viper-development-1.gitbook.io/viperdocs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://viper-development-1.gitbook.io/viperdocs/viper-scripts/multi-job/developer-api/server-events.md).

# Server Events

Server-side event hooks, net events, and the jobs callback for viper-multijob.

These events are fired by viper-multijob with TriggerEvent on the server. Listen to them with AddEventHandler to react to job changes from your own resource. Do not trigger them yourself.

## Quick reference

| Event                                           | Fired when                                              |
| ----------------------------------------------- | ------------------------------------------------------- |
| [jobAdded](#viper-multijobserverjobadded)       | A job is added or its grade is updated through `AddJob` |
| [jobChanged](#viper-multijobserverjobchanged)   | A player switches job through `SetJob`                  |
| [jobRemoved](#viper-multijobserverjobremoved)   | A job is removed from the player                        |
| [jobsCleared](#viper-multijobserverjobscleared) | All of a player's jobs are cleared                      |
| [dutyChanged](#viper-multijobserverdutychanged) | The `SetDuty` export changes a player's duty state      |

***

{% hint style="success" %}

#### `viper-multijob:server:jobAdded`

Fired after a job is added or its grade is updated through the AddJob export.

```lua
---@param src number
---@param job string
---@param grade number
AddEventHandler("viper-multijob:server:jobAdded", function(src, job, grade)
    print(("%s gained %s at grade %d"):format(src, job, grade))
end)
```

{% endhint %}

{% hint style="success" %}

#### `viper-multijob:server:jobChanged`

Fired after a player switches to a job through the SetJob export.

```lua
---@param src number
---@param job string
---@param grade number
AddEventHandler("viper-multijob:server:jobChanged", function(src, job, grade)

end)
```

{% endhint %}

{% hint style="success" %}

#### `viper-multijob:server:jobRemoved`

```lua
---@param src number
---@param job string
AddEventHandler("viper-multijob:server:jobRemoved", function(src, job)

end)
```

{% endhint %}

{% hint style="success" %}

#### `viper-multijob:server:jobsCleared`

```lua
---@param src number
AddEventHandler("viper-multijob:server:jobsCleared", function(src)

end)
```

{% endhint %}

{% hint style="success" %}

#### `viper-multijob:server:dutyChanged`

Fired after the SetDuty export changes a player's duty state.

```lua
---@param src number
---@param state boolean
AddEventHandler("viper-multijob:server:dutyChanged", function(src, state)

end)
```

{% endhint %}

***

### Net events

These are the internal net events the NUI uses. They are documented for completeness — prefer the exports, which validate their input and return a result instead of dropping the player.

| Event                         | Side   | Arguments                    |
| ----------------------------- | ------ | ---------------------------- |
| multijob:server:changeJob     | Server | job (string), grade (number) |
| multijob:server:deleteJob     | Server | job (string)                 |
| multijob:server:newJob        | Server | none                         |
| multijob:server:esxToggleDuty | Server | none                         |
| multijob:client:setDuty       | Client | state (boolean)              |

{% hint style="warning" %}
`multijob:server:changeJob` drops the player when the job or grade does not match the database. Use the `SetJob` export instead.
{% endhint %}

All four server events are registered with RegisterNetEvent and read source, so they must be fired from the client with TriggerServerEvent. Triggering them from another server resource will not work.

***

### Server callback

#### multijob:server:getJobs

Returns every job the player owns as a JSON string — decode it before use.

{% tabs %}
{% tab title="QBCore" %}

```lua
QBCore.Functions.TriggerCallback("multijob:server:getJobs", function(result)
    local jobs = json.decode(result)
end)
```

{% endtab %}

{% tab title="ESX" %}

```lua
ESX.TriggerServerCallback("multijob:server:getJobs", function(result)
    local jobs = json.decode(result)
end)
```

{% endtab %}
{% endtabs %}

The client export GetJobs wraps this and decodes it for you.
