> 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/badges/developers/exports.md).

# Exports

Server and client exports - read badges, revoke them, list types and open the Studio.

Call server exports from server scripts and the client export from client scripts.

```lua
local badges = exports.vision_badges
```

## Server exports

| Export                                            | Returns                                       |
| ------------------------------------------------- | --------------------------------------------- |
| `GetBadge(serial)`                                | The [badge payload](#badge-payload), or `nil` |
| `RevokeBadge(serial, by?)`                        | `true` when a valid badge was revoked         |
| `RevokeCitizenBadges(citizenid, badgeType?, by?)` | Number of badges revoked                      |
| `GetBadgeTypes()`                                 | Array of [badge types](#badge-type)           |
| `GetPlayerBadges(source)`                         | Array of `{ serial, type, number }`           |
| `useBadge`                                        | Used by ox\_inventory only. Don't call it.    |

### GetBadge

```lua
local badge = exports.vision_badges:GetBadge(1042)
if badge and badge.status == 'valid' then
    print(badge.name, badge.rank, badge.badgeNumber)
end
```

`serial` is a number (or a numeric string). Returns the badge as the screen draws it, with its **current** status, or `nil` when there is no such badge.

### RevokeBadge

```lua
local revoked = exports.vision_badges:RevokeBadge(serial, by)
```

Voids one badge. `by` (optional) is shown in the Registry as "Revoked by ..."; default: the name of the calling resource. Returns `true` when a valid badge was revoked, `false` when it doesn't exist or was already revoked. Fires the log event `badge_revoked`.

### RevokeCitizenBadges

```lua
local count = exports.vision_badges:RevokeCitizenBadges(citizenid, badgeType, by)
```

Voids every valid badge of a person. `badgeType` (optional) limits it to one badge id; an unknown badge id revokes nothing and returns `0`. Returns the number of badges revoked. Fires the log event `person_revoked`.

### GetBadgeTypes

```lua
local types = exports.vision_badges:GetBadgeTypes()
```

Every badge type (config and Studio), sorted by id, disabled ones included.

### GetPlayerBadges

```lua
local list = exports.vision_badges:GetPlayerBadges(source)
-- { { serial = 1042, type = 'police', number = 'LSPD-1001' }, ... }
```

The badges this player can show right now, the same list `/badge` uses:

* with an inventory: the badge items in the player's inventory, newest serial first;
* without an inventory: the player's own valid badges, newest first (up to 50).

Badges whose type no longer exists are left out.

## Badge payload

Returned by `GetBadge`:

```lua
{
    serial = 1042,                -- database id
    serialText = '001042',        -- as printed on the card
    type = 'police',              -- badge id
    name = 'Alex Morgan',         -- owner's name at issue
    citizenid = 'AB123456',       -- the ID printed on the card (display ID, or the identifier)
    rank = 'Sergeant',            -- rank at issue
    badgeNumber = 'LSPD-1001',
    issued = '2026/10/12',        -- issue date, formatted with Config.UI.DateFormat
    issuer = 'John Smith',        -- issuer's name ('' when unknown)
    status = 'valid',             -- 'valid' | 'revoked' | 'inactive'
    hasPhoto = true,
}
```

| Status     | Meaning                                                                              |
| ---------- | ------------------------------------------------------------------------------------ |
| `valid`    | Not revoked, and the owner still holds one of the badge's jobs (or the check is off) |
| `revoked`  | Voided (Registry, export, or replaced by a newer badge of the same type)             |
| `inactive` | Not revoked, but the owner no longer holds any of the badge's jobs                   |

The photo isn't part of the payload.

## Badge type

Returned by `GetBadgeTypes`: every field of a badge type after validation, except `issuerIds` and `present`.

| Field                           | Type                                                                          |
| ------------------------------- | ----------------------------------------------------------------------------- |
| `id`                            | string                                                                        |
| `source`                        | `'config'`, `'studio'` or `'override'` (a file badge edited in the Studio)    |
| `enabled`                       | boolean                                                                       |
| `label`, `short`                | string                                                                        |
| `design`                        | string or `nil`                                                               |
| `jobs`                          | string\[]                                                                     |
| `issuers`                       | `{ [job] = rule }`                                                            |
| `requireDuty`                   | boolean                                                                       |
| `number`                        | `{ prefix, digits, start, pool }`                                             |
| `code`, `sealTop`, `sealBottom` | string                                                                        |
| `cardTitle`, `cardNotice`       | string or `nil`                                                               |
| `emblem`, `mark`, `metal`       | string                                                                        |
| `logo`                          | string or `nil`                                                               |
| `colors`                        | `{ primary, secondary, accent, leather, card, ink, label, headerText, foil }` |
| `item`, `itemLabel`, `image`    | string or `nil` (`item = nil` means the shared item)                          |

## Client export

### OpenStudio

```lua
exports.vision_badges:OpenStudio()
```

Opens the Badge Studio for the local player, for example from your admin menu. The server checks admin rights first; a player without them gets "You are not allowed to do that." Pair it with `Config.Admin.studioCommand = false` if you don't want the `/badgestudio` command.

## Common uses

{% tabs %}
{% tab title="Void badges on firing" %}

```lua
-- server: in your job / HR script, after removing someone from the police
local function onFired(citizenid)
    local count = exports.vision_badges:RevokeCitizenBadges(citizenid, 'police', 'Police HR')
    print(('%d police badge(s) voided'):format(count))
end
```

{% endtab %}

{% tab title="Badge check command" %}

```lua
-- server: /checkbadge <serial> prints a badge's status for staff
RegisterCommand('checkbadge', function(source, args)
    local serial = tonumber(args[1])
    if not serial then return print('Usage: /checkbadge <serial>') end
    local badge = exports.vision_badges:GetBadge(serial)
    if not badge then return print('No such badge') end
    print(('#%s %s - %s (%s) - %s'):format(badge.serialText, badge.badgeNumber,
        badge.name, badge.rank, badge.status:upper()))
end, true)
```

{% endtab %}

{% tab title="Admin menu button" %}

```lua
-- client: from your own admin menu
RegisterCommand('myadminmenu_badges', function()
    exports.vision_badges:OpenStudio()
end, false)
```

{% endtab %}

{% tab title="Does this player carry a badge?" %}

```lua
-- server
local function carriesBadge(source, badgeType)
    for _, b in ipairs(exports.vision_badges:GetPlayerBadges(source)) do
        if b.type == badgeType then return true, b.number end
    end
    return false
end
```

{% endtab %}
{% endtabs %}


---

# 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/badges/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.
