> For the complete documentation index, see [llms.txt](https://visionstore.gitbook.io/visionstore-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://visionstore.gitbook.io/visionstore-docs/scripts/crafting/developers/exports.md).

# Exports

Every server export - benches, blueprints, permissions, NPC unlocks and Crafting Mastery.

All exports are **server-side**.

```lua
local crafting = exports.Chapo_Crafting
```

## Benches

| Export                                      | Returns                                                                                                                                                      |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GivePortableBench(src, benchType, amount)` | `true, benchIds[]` or `false, reason`. Mints **new** benches and puts them in the player's inventory. `amount` defaults to `1`.                              |
| `GetBenchLevel(benchId)`                    | The bench's overall level.                                                                                                                                   |
| `GetBenchCategoryLevel(benchId, category)`  | The bench's level in one category.                                                                                                                           |
| `GetBenchProgression(benchId)`              | `{ benchId, global = { level, xp, ... }, category = { [key] = { level, xp, ... } } }`, or `nil` for an unknown bench.                                        |
| `AddBenchXP(benchId, category, amount)`     | Adds XP to the bench and that category. Returns `{ xp, level, levelledUp, categoryXP, categoryLevel, categoryLevelledUp }`, or `false` for an unknown bench. |
| `GetBenchLocation(benchId)`                 | `{ locationId, benchType, coords, heading, bucket, propertyId }`, or `nil` when the bench is in someone's pocket.                                            |
| `GetCatalogue()`                            | `{ categories, recipes, benches, blueprints }` as loaded from the config.                                                                                    |
| `GrantBlueprint(src, blueprintKey, uses)`   | Teaches a player a blueprint. `uses` is optional. Returns `true` / `false`.                                                                                  |

`GivePortableBench` refuses with `'unknown_bench_type'` or `'not_portable'`. Every call creates new, independent benches: calling it five times gives five benches, never five copies of one.

## Players

| Export                                 | Returns                                                                                                 |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `IsCraftingAdmin(src)`                 | `true` if the player is crafting staff.                                                                 |
| `CanUseCrafting(src)`                  | `true` if the player may use the crafting system (only `false` in `'admin'` access mode for non-staff). |
| `HasWorkbenchUnlocked(src, workbench)` | `true` if the player completed the hidden NPC that grants this unlock id.                               |
| `GetUnlockedWorkbenches(src)`          | A list of unlock ids, for example `{ 'tools', 'medical' }`.                                             |

## Crafting Mastery

Bench progression is what a **table** can do. Mastery is what a **character** can do. If Mastery is disabled, these return neutral values (`nil`, `0`, `false` or zero effects) instead of erroring.

| Export                              | Returns                                                                                                             |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `GetMastery(src)`                   | The player's whole mastery state (XP, unlocks, equipped perks, slots, bonuses), the same data the UI shows.         |
| `GetMasteryEffects(src)`            | The bonuses running now, as fractions: `{ craftSpeed, repairSpeed, xpGain, damageReduction }`. Equipped perks only. |
| `HasMasteryPerk(src, perkKey)`      | `true` if the perk is **unlocked** (e.g. `'speed_2'`).                                                              |
| `IsMasteryPerkActive(src, perkKey)` | `true` if the perk is **equipped**.                                                                                 |
| `GetMasteryLifetimeXP(src)`         | Total Mastery XP ever earned. Only goes up: the number to rank a leaderboard on.                                    |
| `AddMasteryXP(src, amount, reason)` | Grants Mastery XP. Counts toward the daily soft cap. Returns the amount credited.                                   |
| `GetMasteryTree()`                  | The tree definition with no player attached, for wikis and Discord bots.                                            |

Perk keys are the tier `key`s in `config/mastery.lua`: `speed_1`-`speed_4`, `maint_1`-`maint_5`, `know_1`-`know_6`, `handling_1`-`handling_3`.

## Examples

{% tabs %}
{% tab title="Sell a bench in a shop" %}

```lua
-- server.lua of your shop
RegisterNetEvent('myshop:buyToolsBench', function()
    local src = source
    -- take the money with your framework first, then:
    local ok, result = exports.Chapo_Crafting:GivePortableBench(src, 'tools', 1)
    if not ok then
        print(('could not give bench: %s'):format(tostring(result)))
        -- refund the player here
        return
    end
    print(('gave bench %s to %d'):format(result[1], src))
end)
```

{% endtab %}

{% tab title="Quest reward: a blueprint" %}

```lua
-- Requires a 'pistol' entry in config/blueprints.lua
local function finishGunsmithQuest(src)
    if exports.Chapo_Crafting:GrantBlueprint(src, 'pistol') then
        TriggerClientEvent('ox_lib:notify', src, {
            description = 'You learned the Pistol Blueprint.',
            type = 'success',
        })
    end
end
```

{% endtab %}

{% tab title="Job perk for veteran crafters" %}

```lua
-- Only crafters with Careful Handling equipped may take this contract
local function canTakeContract(src)
    return exports.Chapo_Crafting:IsMasteryPerkActive(src, 'handling_1')
        or exports.Chapo_Crafting:IsMasteryPerkActive(src, 'handling_2')
        or exports.Chapo_Crafting:IsMasteryPerkActive(src, 'handling_3')
end
```

{% endtab %}

{% tab title="Where is this bench?" %}

```lua
local location = exports.Chapo_Crafting:GetBenchLocation(benchId)
if location then
    print(('bench at %.1f %.1f %.1f (bucket %s)'):format(
        location.coords.x, location.coords.y, location.coords.z, tostring(location.bucket or 0)))
else
    print('bench is in an inventory')
end
```

{% endtab %}
{% endtabs %}

## Using bench items with ox\_inventory

The bench items call this export through ox\_inventory. You don't call it yourself, but it must be on every bench item:

```lua
server = { export = 'Chapo_Crafting.usePortableBench' },
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://visionstore.gitbook.io/visionstore-docs/scripts/crafting/developers/exports.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
