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

# Logbook

> Create logbook entries, read a user's history, check rank locks, and attach comments.

The logbook is BloxCord's moderation and administration record for each user. These methods let your game read and write it in real time.

## Locked & classified visibility

Two fields control who can see a logbook entry:

* **`locked`** — an array of **role ids** allowed to view/unlock the entry.
* **`classified`** — an array of **role ids** allowed to view a classified entry.

An **empty array** (`{}`) means no restriction. You provide these role ids when [creating an entry](#createlogbookentry), and [`getLogbookEntries`](#getlogbookentries) returns them back as arrays.

<Note>
  Legacy entries created before role-scoped visibility stored a plain boolean. When such an entry is read, its `locked` / `classified` value is returned as the single-element array `{ "legacy_role" }` instead of a boolean.
</Note>

<Note>
  Lokced & classified entries are an enterprise-only feature.
</Note>

## createLogbookEntry

Creates a new logbook entry (warning, ban, mute, rank lock, etc.) for a user.

```lua theme={null}
local result = BloxCord:Invoke("createLogbookEntry", actor, target, opts)
```

### Parameters

<ParamField body="actor" type="Player | table | number" required>
  Who is issuing the entry. See [the actor object](/gi-concepts#the-actor-object).
</ParamField>

<ParamField body="target" type="Player | number | string" required>
  The user receiving the entry. Accepts a `Player` instance or a raw `UserId`.
</ParamField>

<ParamField body="opts" type="table" required>
  Entry options.

  <Expandable title="opts fields">
    <ParamField body="type" type="string" required>
      The logbook entry type (e.g. `"warning"`, `"tban"`, `"mute"`, `"rlock"`).
    </ParamField>

    <ParamField body="reason" type="string">
      Human-readable reason for the entry.
    </ParamField>

    <ParamField body="expiry" type="number">
      Unix timestamp (ms) at which the entry expires. Omit for a permanent entry.
    </ParamField>

    <ParamField body="mban" default="false" type="boolean">
      Whether this is a machine ban. (Open-Cloud User Restrictions API - Alt Block)
    </ParamField>

    <ParamField body="locked" type="string[]">
      Array of **role ids** permitted to view/unlock the entry. Omit or pass an empty array for no restriction.
    </ParamField>

    <ParamField body="classified" type="string[]">
      Array of **role ids** permitted to view the entry when classified. Omit or pass an empty array for no restriction.
    </ParamField>

    <ParamField body="rules" type="table">
      Optional rule references associated with the entry.
    </ParamField>
  </Expandable>
</ParamField>

### Returns

<ResponseField name="result" type="table | nil">
  The created entry payload from the dashboard on success, or `nil` if the request was rejected or the backend was unreachable.
</ResponseField>

### Example

```lua theme={null}
local BloxCord = game:WaitForChild("BloxCord")

BloxCord:Invoke("createLogbookEntry", moderator, offender, {
    type = "warning",
    reason = "Spamming in chat",
    expiry = os.time() * 1000 + (7 * 24 * 60 * 60 * 1000), -- 7 days
    locked = { "role_235235235seniorstaff", "role_hr" }, -- only these roles can view/unlock. Note that these are role IDs, not role names.
})
```

***

## getLogbookEntries

Fetches a user's logbook entries, optionally filtered by type and active state.

```lua theme={null}
local entries = BloxCord:Invoke("getLogbookEntries", userId, filters)
```

### Parameters

<ParamField body="userId" type="number | string" required>
  The `UserId` whose entries to fetch.
</ParamField>

<ParamField body="filters" type="table">
  Optional filters.

  <Expandable title="filters fields">
    <ParamField body="type" type="string">
      Only return entries of this type (e.g. `"tban"`, `"rlock"`).
    </ParamField>

    <ParamField body="active" type="boolean">
      When `true`, only return entries that are not reverted and not expired.
    </ParamField>
  </Expandable>
</ParamField>

### Returns

<ResponseField name="entries" type="object[]">
  An array of logbook entries. Empty if none match or the request failed.

  <Expandable title="entry fields">
    <ResponseField name="id" type="string">
      Unique entry id.
    </ResponseField>

    <ResponseField name="type" type="string">
      Entry type.
    </ResponseField>

    <ResponseField name="reason" type="string">
      Reason text.
    </ResponseField>

    <ResponseField name="rank" type="number">
      Target's rank at time of entry.
    </ResponseField>

    <ResponseField name="role" type="string">
      Target's role at time of entry.
    </ResponseField>

    <ResponseField name="newrank" type="number">
      New rank (for rank changes).
    </ResponseField>

    <ResponseField name="newrole" type="string">
      New role (for rank changes).
    </ResponseField>

    <ResponseField name="duration" type="number">
      Duration, if applicable.
    </ResponseField>

    <ResponseField name="time" type="number">
      Creation timestamp (ms).
    </ResponseField>

    <ResponseField name="expiry" type="number | null">
      Expiry timestamp (ms), or null if permanent.
    </ResponseField>

    <ResponseField name="reverted" type="boolean">
      Whether the entry was reverted.
    </ResponseField>

    <ResponseField name="locked" type="string[]">
      Array of role ids allowed to view/unlock the entry. Empty if unrestricted. Legacy entries return `{ "legacy_role" }`.
    </ResponseField>

    <ResponseField name="classified" type="string[]">
      Array of role ids allowed to view the classified entry. Empty if unrestricted. Legacy entries return `{ "legacy_role" }`.
    </ResponseField>

    <ResponseField name="moderator" type="object">
      The actor who created the entry.
    </ResponseField>
  </Expandable>
</ResponseField>

### Example

```lua theme={null}
local BloxCord = game:WaitForChild("BloxCord")

local activeBans = BloxCord:Invoke("getLogbookEntries", player.UserId, {
    type = "ban",
    active = true,
})

if #activeBans > 0 then
    local ban = activeBans[1]
    if #ban.locked > 0 then
        print("Entry is locked to roles:", table.concat(ban.locked, ", "))
    end
    player:Kick("You are banned: " .. ban.reason)
end
```

***

## checkranklock

Convenience check for whether a user currently has an active **rank lock** (`rlock`) entry. Equivalent to calling [`getLogbookEntries`](#getlogbookentries) with `type = "rlock"` and `active = true` and testing for results.

```lua theme={null}
local locked = BloxCord:Invoke("checkranklock", userId)
```

### Parameters

<ParamField body="userId" type="number | string" required>
  The `UserId` to check.
</ParamField>

### Returns

<ResponseField name="locked" type="boolean">
  `true` if the user has at least one active rank lock, otherwise `false`.
</ResponseField>

### Example

```lua theme={null}
local BloxCord = game:WaitForChild("BloxCord")

if BloxCord:Invoke("checkranklock", targetUserId) then
    warn("Cannot rank this user — they are rank-locked.")
    return
end
```
