# Client Storage

Client storage is available through **`/api/v2/storage`** and is scoped to a hub. Entries can be attached to a key, a HWID, or both. The API uses a 2 MB limit per storage namespace.

{% hint style="info" %}
Use `key: "x"` or omit `key` for free-for-all storage entries. Creating, updating, or deleting by value requires either a HWID or a non-`x` key.
{% endhint %}

## List Storage

**`GET`** `/api/v2/storage`

#### Query

| Query   | Description                                                             |
| ------- | ----------------------------------------------------------------------- |
| hubId   | Hub ID to fetch storage from. Required.                                 |
| key     | Optional key filter. Use `x` for free-for-all entries.                  |
| hwid    | Optional HWID filter.                                                   |
| valueId | Optional value ID search.                                               |
| exact   | Optional. Use `1` to fetch one exact entry and include its full `data`. |

{% hint style="warning" %}
Exact lookups require `valueId` plus either `key` or `hwid`.
{% endhint %}

#### Response

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

```json
{
  "success": true,
  "message": "Successfully fetched storage entries.",
  "entries": [
    {
      "id": "662fe6bf16fa4b85d7e06c57",
      "key": "73978994376e1f3e307914c4",
      "isFreeForAll": false,
      "hwid": "589401805431295092384985734",
      "valueId": "coins",
      "sizeBytes": 5,
      "dataType": "number",
      "preview": "25000"
    }
  ],
  "totalEntries": 1,
  "totalBytes": 5,
  "maxBytes": 2097152
}
```

{% endtab %}

{% tab title="200 exact" %}

```json
{
  "success": true,
  "message": "Successfully fetched storage entry.",
  "entry": {
    "id": "662fe6bf16fa4b85d7e06c57",
    "key": "73978994376e1f3e307914c4",
    "isFreeForAll": false,
    "hwid": "589401805431295092384985734",
    "valueId": "coins",
    "sizeBytes": 5,
    "dataType": "number",
    "preview": "25000",
    "data": 25000
  }
}
```

{% endtab %}
{% endtabs %}

## Create Storage

**`POST`** `/api/v2/storage`

#### Payload

```json
{
  "hubId": "40511091490620200512",
  "key": "73978994376e1f3e307914c4",
  "hwid": "589401805431295092384985734",
  "valueId": "coins",
  "data": 25000
}
```

{% hint style="info" %}
`data` can be a string, number, or boolean. `valueId` must be between 4 and 128 characters.
{% endhint %}

#### Response

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

```json
{
  "success": true,
  "message": "Storage entry created.",
  "entry": {
    "id": "",
    "key": "73978994376e1f3e307914c4",
    "isFreeForAll": false,
    "hwid": "589401805431295092384985734",
    "valueId": "coins",
    "sizeBytes": 5,
    "dataType": "number",
    "preview": "25000"
  }
}
```

{% endtab %}

{% tab title="409" %}

```json
{
  "success": false,
  "message": "Storage entry already exists."
}
```

{% endtab %}
{% endtabs %}

## Update Storage

**`PATCH`** `/api/v2/storage`

#### Payload

```json
{
  "hubId": "40511091490620200512",
  "originalKey": "73978994376e1f3e307914c4",
  "originalHwid": "589401805431295092384985734",
  "originalValueId": "coins",
  "key": "73978994376e1f3e307914c4",
  "hwid": "589401805431295092384985734",
  "valueId": "coins",
  "data": 30000
}
```

{% hint style="warning" %}
The `original*` fields identify the existing entry. The non-original `key`, `hwid`, and `valueId` become the new location for the entry.
{% endhint %}

#### Response

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

```json
{
  "success": true,
  "message": "Storage entry updated.",
  "entry": {
    "id": "",
    "key": "73978994376e1f3e307914c4",
    "isFreeForAll": false,
    "hwid": "589401805431295092384985734",
    "valueId": "coins",
    "sizeBytes": 5,
    "dataType": "number",
    "preview": "30000"
  }
}
```

{% endtab %}

{% tab title="404" %}

```json
{
  "success": false,
  "message": "Storage entry not found."
}
```

{% endtab %}
{% endtabs %}

## Delete Storage

**`DELETE`** `/api/v2/storage`

#### Query

| Query   | Description                                                          |
| ------- | -------------------------------------------------------------------- |
| hubId   | Hub ID the storage entry belongs to. Required.                       |
| valueId | Value ID to delete. Required by the current validator.               |
| id      | Optional internal storage entry ID. If given, deletion uses this ID. |
| key     | Optional key for value-based deletion.                               |
| hwid    | Optional HWID for value-based deletion.                              |

{% hint style="warning" %}
When `id` is not used, deleting storage requires `valueId` plus either `key` or `hwid`.
{% endhint %}

#### Response

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

```json
{
  "success": true,
  "message": "Storage entry deleted."
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "success": false,
  "message": "Deleting storage requires a key or HWID."
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.luaprot.net/luaprot/api-documentation/storage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
