Quick Start
Get Network Storage running in your s&box game in 5 minutes. This path uses server-side authority: the player asks to do something, the endpoint decides whether...
# Quick Start
Get Network Storage running in your s&box game in 5 minutes. This path uses server-side authority: the player asks to do something, the endpoint decides whether it is allowed, and endpoint-controlled collections block direct client writes.
## Fast Track: one call instead of manual HTTP/Auth
With the official s&box library, a secure purchase is one await call from game code:
```csharp
var result = await NetworkStorage.CallEndpoint( "purchase-item", new
{
item_id = "sports_car"
} );
```
The library handles request setup, auth context, response parsing, and errors. The sboxcool.com API verifies the s&box/Steam auth handshake server-side, so you do not need to write a separate Node.js or Python backend just to exchange tokens, call the Facepunch API, and protect your economy.
## 1. Install the Library
Install **Network Storage by sboxcool.com** from the s&box Library Manager:
**[sbox.game/sboxcool/network-storage](https://sbox.game/sboxcool/network-storage)**
Or open **Editor > Library Manager** in the s&box editor and search for `Network Storage by sboxcool.com`. Source: [github.com/sbox-cool/sbox-network-storage](https://github.com/sbox-cool/sbox-network-storage).
This gives you:
- `NetworkStorage` — the API client (game code)
- Sync Tool — editor window for managing your data (Editor → Network Storage)
## 2. Create a Project
Go to [sboxcool.com/tools/network-storage](https://sboxcool.com/tools/network-storage) and click **New Project**. Give it a name. You'll get:
- A **Project ID** (e.g. `2db44af465f4498d`) -- identifies your project in API URLs and library config
- A **Public API Key** (`sbox_ns_...`) -- used with the Project ID by your game or dedicated server to call endpoints and load game values
- A **Secret Key** (`sbox_sk_...`) -- used only by the editor Sync Tool and Management API to push collections, endpoints, workflows, and settings. It never gets exported to published game files
## 3. Configure the Library
Use the **Setup Tool** to connect the library to your project:
1. Open **Editor → Network Storage → Setup**
2. Enter your **Project ID**, **Public Key**, and **Secret Key** from the dashboard
3. Click **Save Configuration**, then **Test Connection**
The setup tool stores the secret key in the editor-only config and generates the runtime config your game auto-loads on first use. Published builds only need the Project ID + Public Key at runtime.
Alternatively, create a config class in your game code:
```csharp
namespace Sandbox;
public static class NetworkStorageConfig
{
public const string ProjectId = "YOUR_PROJECT_ID";
public const string PublicKey = "sbox_ns_YOUR_KEY";
public static void Initialize()
{
NetworkStorage.Configure( ProjectId, PublicKey );
}
}
```
Call `NetworkStorageConfig.Initialize()` once at game startup (e.g. in your player's `OnStart`).
## 4. Create Endpoint-Only Collections
On the dashboard, open your project and click **New Collection**:
- **Name**: `players`
- **Type**: Per-Player
- **Access Mode**: Endpoint controlled
Paste this schema into the schema editor:
```yml
type: object
properties:
playerName:
type: string
xp:
type: number
min: 0
gold:
type: number
min: 0
inventory:
type: array
items:
type: string
```
Click **Create Collection**.
Endpoint controlled is the security boundary. Published game clients can call endpoints, but they cannot write `gold`, `inventory`, or other protected fields directly.
## 5. Create a Shop Game Value Table
Open **Game Values** and create a `shop_items` table with an item id and price. Example rows:
| id | name | price |
|----|------|-------|
| `sports_car` | Sports Car | `45000` |
| `starter_hat` | Starter Hat | `100` |
The Editor Sync Tool can keep this table in your project and push it to the cloud. Your client UI can read the same values for predicted prices while the backend endpoint validates against the authoritative cloud copy.
## 6. Create a Secure Purchase Endpoint
On the dashboard, go to **Endpoints** and click **New Endpoint**:
- **Name**: `Purchase Item`
- **Slug**: `purchase-item`
- **Method**: POST
In the endpoint editor, use the **YAML Source** tab. YAML Source is the current standard for new endpoints:
```yml
sourceVersion: "1"
kind: endpoint
name: Purchase Item
slug: purchase-item
method: POST
enabled: true
input:
type: object
properties:
item_id:
type: string
required:
- item_id
steps:
- id: player
type: read
collection: players
key: "{{steamId}}_default"
- id: item
type: lookup
source: values
table: shop_items
where:
field: id
op: "=="
value: "{{input.item_id}}"
- id: can_afford
type: condition
check:
field: player.gold
op: ">="
value: "{{item.price}}"
onFail:
status: 400
error: INSUFFICIENT_FUNDS
message: "Not enough gold"
- id: purchase
type: write
collection: players
key: "{{steamId}}_default"
ops:
- op: inc
path: gold
value: "{{-item.price}}"
source: purchase
reason: "Bought {{input.item_id}}"
- op: push
path: inventory
value: "{{input.item_id}}"
source: purchase
reason: "Bought {{input.item_id}}"
response:
status: 200
body:
success: true
item_id: "{{input.item_id}}"
price: "{{item.price}}"
gold_remaining: "{{purchase.gold}}"
```
Click **Save Endpoint**.
This template shows the core purchase workflow:
- Steam identity is verified before the endpoint runs
- Price comes from the `shop_items` Game Value table
- Balance is read from the protected `players` collection
- The write only happens if the condition passes
- The client receives success/fail data without being trusted to choose the result
### Want something more advanced? Here's `report-kill`:
This endpoint reads a Game Value for the XP reward, then increments the player's XP and kill counter:
```yml
sourceVersion: "1"
kind: endpoint
name: Report Kill
slug: report-kill
method: POST
enabled: true
input:
type: object
properties:
target_type:
type: string
required:
- target_type
steps:
- id: xp_amount
type: transform
value: "{{values.combat.xp_per_kill}}"
- id: award
type: write
collection: players
key: "{{steamId}}_default"
ops:
- op: inc
path: xp
value: "{{xp_amount}}"
source: combat
reason: "Killed {{input.target_type}}"
- op: inc
path: stats.kills
value: 1
response:
status: 200
body:
success: true
xp_earned: "{{xp_amount}}"
```
The `transform` step pulls `xp_per_kill` from your Game Values (set up in the dashboard), so you can rebalance rewards without touching game code.
## 7. Call It From Your Game
```csharp
// Call the endpoint — auth is handled automatically
var result = await NetworkStorage.CallEndpoint( "purchase-item", new
{
item_id = "sports_car"
} );
if ( result.HasValue && result.Value.Bool( "success" ) )
{
int goldRemaining = result.Value.Int( "gold_remaining" );
Log.Info( $"Purchased car. Gold remaining: {goldRemaining}" );
}
else
{
Log.Warning( "Purchase failed." );
}
```
## 8. Read Player Data Through an Endpoint
Game clients should read collection data through endpoints or queries. Direct collection reads require a secret key and are intended for dedicated-server/backoffice tooling.
```csharp
var player = await NetworkStorage.CallEndpoint( "get-player-profile", new { } );
if ( player.HasValue )
{
string name = player.Value.Str( "playerName" );
int xp = player.Value.Int( "xp" );
Log.Info( $"{name} has {xp} XP" );
}
```
That's it. Your game is now using server-authoritative storage. The client can't cheat — all game logic runs on the server through your endpoints.
## What's Next
- [Library Setup Guide](/wiki/network-storage-v3/library-setup) — install and configure the s&box library
- [Library Reference](/wiki/network-storage-v3/library-reference) — full API docs for all classes and methods
- [Source Authoring](/wiki/network-storage-v3/source-authoring) -- full YAML Source syntax, steps, inputs, outputs, and compiler options
- [Collections](/wiki/network-storage-v3/collections) — schemas, access model, storage types
- [Endpoints](/wiki/network-storage-v3/endpoints) — building server-side logic pipelines
- [Sync Tools](/wiki/network-storage-v3/sync-tools) — managing data from the s&box editor
- [Agent Discovery](/wiki/network-storage-v3/agent-discovery) — machine-friendly manifest and runtime contract for automation
- [Example: RPG Game](/wiki/network-storage-v3/code-examples/example-rpg) — complete end-to-end example
## Library Reference
Use the Network Storage library methods in game code instead of building raw requests.
| What | Library call |
|------|--------------|
| Configure | `NetworkStorage.Configure( projectId, publicKey )` |
| Call endpoint | `NetworkStorage.CallEndpoint( "slug", input )` |
| Get game values | `NetworkStorage.GetGameValues()` |
| Read document | Use an endpoint/query from game clients; `GetDocument` is for trusted server tooling |
| Create/replace document | Use an endpoint from game clients; `SaveDocument` is for trusted server tooling |
| Edit document | `NetworkStorage.UpdateDocument( "collection", "documentId", ops )` |
| Remove document | `NetworkStorage.DeleteDocument( "collection", "documentId" )` |
| Host proxy call | `NetworkStorage.CallEndpointAs( steamId, clientToken, "slug", input )` |