> ## Documentation Index
> Fetch the complete documentation index at: https://docs.projectx.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Exports

> Available exports for the Project X XP skill system

## Server Exports

### AddXP

Awards XP to a player for a skill. Active XP buffs are applied using:

```text theme={null}
floor((baseXp + flatBonusTotal) * multiplierTotal)
```

```lua theme={null}
local ok, result = exports['projectx-xp']:AddXP(source, skillId, amount)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills` (e.g. `'criminal'`)
</ParamField>

<ParamField path="amount" type="number" required>
  Base XP to award before buffs
</ParamField>

**Returns**

* `ok` (boolean) — `true` on success, `false` on failure
* `result` (table | string)
  * On success (table):
    * `skill` (string) — skill ID
    * `amount` (number) — XP awarded after buffs
    * `xp` (number) — current XP toward the next level
    * `totalXp` (number) — lifetime XP for the skill
    * `level` (number) — current level
    * `previousLevel` (number) — level before this award
    * `leveledUp` (boolean) — whether the player leveled up
    * `milestones` (table) — milestones reached from this award (if any)
  * On failure (string), common values include:
    * `'invalid_player'`
    * `'invalid_skill'`
    * `'invalid_amount'`
    * `'max_level'`

**Example**

```lua theme={null}
local ok, result = exports['projectx-xp']:AddXP(source, 'criminal', 50)
if ok then
    print(('Awarded %s XP — now level %s'):format(result.amount, result.level))
else
    print('AddXP failed:', result)
end
```

***

### AddXPRaw

Awards XP while **ignoring** active XP buffs (no multiplier or flat bonus applied).

```lua theme={null}
local ok, result = exports['projectx-xp']:AddXPRaw(source, skillId, amount)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

<ParamField path="amount" type="number" required>
  Exact XP to award
</ParamField>

**Returns**

Same shape as [`AddXP`](#addxp).

***

### RemoveXP

Removes XP from a player for a skill.

```lua theme={null}
local ok, result = exports['projectx-xp']:RemoveXP(source, skillId, amount)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

<ParamField path="amount" type="number" required>
  XP to remove
</ParamField>

**Returns**

* `ok` (boolean)
* `result` (table | string) — updated skill state on success, or an error string on failure

***

### SetLevel

Sets a player's level for a skill directly.

<Warning>
  `SetLevel` does **not** re-grant milestone rewards for levels the player skips or is set to.
</Warning>

```lua theme={null}
local ok, result = exports['projectx-xp']:SetLevel(source, skillId, level)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

<ParamField path="level" type="number" required>
  Target level (clamped to the skill's `MaxLevel`)
</ParamField>

**Returns**

* `ok` (boolean)
* `result` (table | string) — updated skill state on success, or an error string on failure

***

### GetSkill

Returns a single skill record for a player.

```lua theme={null}
local skill = exports['projectx-xp']:GetSkill(source, skillId)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

**Returns**

* `table` or `nil` — skill data (`level`, `xp`, `totalXp`, etc.)

***

### GetSkills

Returns all skill records for a player.

```lua theme={null}
local skills = exports['projectx-xp']:GetSkills(source)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

**Returns**

* `table` — map of skill ID → skill data

***

### GetLevel

Returns the player's current level for a skill.

```lua theme={null}
local level = exports['projectx-xp']:GetLevel(source, skillId)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

**Returns**

* `number` — current level (typically `0` if missing)

***

### GetTotalXp

Returns the player's total (lifetime) XP for a skill.

```lua theme={null}
local totalXp = exports['projectx-xp']:GetTotalXp(source, skillId)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

**Returns**

* `number` — total XP

***

### GetSkillIds

Returns the configured skill IDs.

```lua theme={null}
local skillIds = exports['projectx-xp']:GetSkillIds()
```

**Returns**

* `table` — list of skill ID strings

***

### OpenMenu

Opens the XP menu for a player from the server.

```lua theme={null}
exports['projectx-xp']:OpenMenu(source)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

***

### SyncClient

Forces a client sync of the player's XP data.

```lua theme={null}
exports['projectx-xp']:SyncClient(source)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

***

### AddXpBuff

Adds a temporary XP buff. Multiple buffs stack.

Award formula while buffs are active:

```text theme={null}
floor((baseXp + flatBonusTotal) * multiplierTotal)
```

```lua theme={null}
local ok, result = exports['projectx-xp']:AddXpBuff(source, options)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="options" type="table" required>
  Buff options table
</ParamField>

<ParamField path="options.skill" type="string">
  Skill ID to apply the buff to, or a value that targets all skills depending on your config
</ParamField>

<ParamField path="options.multiplier" type="number">
  Multiplier contribution (e.g. `1.5` for +50%)
</ParamField>

<ParamField path="options.flatBonus" type="number">
  Flat XP added before the multiplier is applied
</ParamField>

<ParamField path="options.duration" type="number">
  Buff duration in seconds
</ParamField>

<ParamField path="options.label" type="string">
  Display label shown in notifications / UI
</ParamField>

<ParamField path="options.id" type="string">
  Optional unique buff ID (useful for targeted removal)
</ParamField>

<ParamField path="options.notify" type="boolean">
  Whether to notify the player when the buff is applied
</ParamField>

**Example**

```lua theme={null}
exports['projectx-xp']:AddXpBuff(source, {
    skill = 'criminal',
    multiplier = 1.5,
    flatBonus = 10,
    duration = 300,
    label = 'Heist Boost',
    id = 'heist_boost',
    notify = true,
})
```

***

### RemoveXpBuff

Removes an active XP buff by ID (or matching options, depending on usage).

```lua theme={null}
local ok = exports['projectx-xp']:RemoveXpBuff(source, buffId)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="buffId" type="string" required>
  Buff ID previously passed to `AddXpBuff`
</ParamField>

**Returns**

* `boolean` — whether a buff was removed

***

### GetXpBuffs

Returns active XP buffs for a player.

```lua theme={null}
local buffs = exports['projectx-xp']:GetXpBuffs(source, skillId)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string">
  Optional skill filter
</ParamField>

**Returns**

* `table` — list of active buffs

***

### GetXpMultiplier

Returns the combined XP multiplier (and related totals) currently applied for a skill.

```lua theme={null}
local multiplier = exports['projectx-xp']:GetXpMultiplier(source, skillId)
```

<ParamField path="source" type="number" required>
  Player server ID
</ParamField>

<ParamField path="skillId" type="string" required>
  Skill ID from `Config.Skills`
</ParamField>

**Returns**

* `number` — combined multiplier total used by `AddXP`

***

## Client Exports

### OpenMenu

Opens the XP menu on the local client.

```lua theme={null}
exports['projectx-xp']:OpenMenu()
```

***

### IsMenuOpen

Returns whether the XP menu is currently open.

```lua theme={null}
local open = exports['projectx-xp']:IsMenuOpen()
```

**Returns**

* `boolean`

***

### RefreshMenu

Refreshes the XP menu UI if it is open.

```lua theme={null}
exports['projectx-xp']:RefreshMenu()
```

***

### GetXpBuffs

Returns active XP buffs known to the client.

```lua theme={null}
local buffs = exports['projectx-xp']:GetXpBuffs(skillId)
```

<ParamField path="skillId" type="string">
  Optional skill filter
</ParamField>

**Returns**

* `table` — list of active buffs

***

## Bridge Integration

When `XPSystem` is set to `'projectx'` (or `'auto'` and projectx-xp is running), Project X scripts can award and read XP through the bridge:

```lua theme={null}
exports['projectx-bridge']:AddExperience(source, 'criminal', 25)
exports['projectx-bridge']:GetLevel(source, 'criminal')
```

See [Bridge Installation](/resources/bridge/installation) for `XPSystem` options.

## Example: Robbery / Job Award

```lua theme={null}
-- Server-side only
local ok, result = exports['projectx-xp']:AddXP(source, 'criminal', 50)
if ok and result.leveledUp then
    print(('Player reached criminal level %s'):format(result.level))
end
```

<Warning>
  Do not call `AddXP` (or any XP-mutating export) from client scripts. Award XP on the server only.
</Warning>
