Skip to main content
A Personal Server is the user’s access engine: it holds (a reference to) the user’s data and decides, per request, whether to release a scope to a builder. It is where grants are enforced, data is served, and access is logged. It is the only protocol component that works with plaintext data. It runs the Vana SDK — encryption, decryption, permission checks, and identity — so the trust-bearing logic executes under the user’s control, not on a builder’s servers. Today the Personal Server is client-side: it runs on the user’s own device, bundled into the desktop app, or in a browser tab for the web.
A Personal Server is a protocol participant — it registers onchain and can act under the scopes the user allows. A Vana app (the desktop app, or a web app) is a client that bundles and controls a Personal Server, but is not itself a protocol participant. Think of it like email: the app is your mail client, the Personal Server is your mail server.

What every Personal Server does

  • Syncs data from the user’s connected sources into their own storage, organized by scope
  • Serves data to builders who hold a valid grant, scope by scope, over an authenticated API
  • Encrypts data before uploading to storage backends
  • Validates grants on every request — registered grantee, unrevoked, unexpired, scope covered, and (where fee gating is enabled) fee paid
  • Exposes an MCP interface so agents can work with the user’s data under the same grant permissions — bounding what an agent may access (see Agents)
  • Keeps an access log the user can review
Today the Personal Server is the entity that decrypts and returns a requested scope to a grantee. With Protocol-Governed Encryption (PGE) the grantee receives a per-request key and decrypts the data itself; the grant interface a builder integrates with is the same regardless of where decryption happens.

Forms

FormWhere it runsStorageStatus
Desktop (Full)Bundled in the desktop app, running locally on the user’s machineFilesystemLive
Web (Lite)A separate browser tab on the user’s deviceIn-browser (IndexedDB)Live
User computeA compute environment the user fully controls (see below)FilesystemFuture
The desktop and web forms share one codebase and one SDK; they differ only in where they run and how they store data. Both keep the data and keys on the client. The desktop form keeps keys in the OS filesystem; the Web (Lite) form keeps them in the browser (IndexedDB) for zero-install convenience.

Registration

Every Personal Server must be registered onchain via the DataPortabilityServers contract. Registration records the server’s address, public key, and URL. Users then trust a server to act on their behalf. The DP RPC provides signature-based registration so a Vana app can register a server without the user sending an onchain transaction directly:
POST /v1/servers
See Identity for the full registration flow and the DataPortabilityServers contract interface.

API

The Personal Server exposes a versioned REST API under /v1.

Data endpoints

MethodPathDescription
POST/v1/data/{scope}Create a new data document for a scope
GET/v1/dataList available scopes and latest version metadata
GET/v1/data/{scope}Read data for a scope (latest or specific version)
GET/v1/data/{scope}/versionsList available versions (metadata only)
DELETE/v1/data/{scope}Delete data for a scope (user-only)

Grant endpoints

MethodPathDescription
GET/v1/grantsList all grants for this user
POST/v1/grantsCreate a new grant (user-only)
POST/v1/grants/verifyVerify a grant signature

Other endpoints

MethodPathDescription
GET/v1/access-logsGet access log history
GET/healthHealth check (unversioned)

Query parameters for GET /v1/data

ParameterDescription
scopePrefixFilter by scope prefix (e.g. instagram)
limitMaximum number of results
offsetPagination offset

Query parameters for GET /v1/data/{scope}

ParameterDescription
fileIdReturn a specific version by DataRegistry fileId
atReturn the version closest to this ISO 8601 timestamp (closest ≤ at)
If neither parameter is provided, the latest version by collectedAt is returned.

Write flow (POST /v1/data/{scope})

When a data document is written:
  1. Look up schemaId for the scope via the DP RPC
  2. Validate the request body against the schema
  3. Generate a collectedAt timestamp (UTC)
  4. Construct the data file envelope with schema URL, version, scope, and timestamp
  5. Store locally in ~/.vana/data/{scope}/{collectedAt}.json
  6. Return 201 Created immediately
  7. Asynchronously: encrypt with the scope key, upload to the storage backend, and register in the DataRegistry

Builder data access

Builders read data from the Personal Server using signed HTTP requests. Every builder request must include an Authorization: Web3Signed header.

Web3Signed authorization

Authorization: Web3Signed <base64url(json)>.<signature>
The payload is a JSON object with keys sorted alphabetically:
{
  "aud": "https://user-abc.server.vana.com",
  "bodyHash": "",
  "exp": 1737500300,
  "grantId": "0x...",
  "iat": 1737500000,
  "method": "GET",
  "uri": "/data/instagram.profile"
}
FieldDescription
audPersonal Server origin (must match)
methodHTTP method of the request
uriRequest path and query string
bodyHashHash of request body (empty string for GET)
iatIssued-at timestamp (Unix seconds)
expExpiration timestamp (Unix seconds)
grantIdOnchain permissionIdrequired for raw data reads
Signing: The JSON is canonicalized (keys sorted alphabetically), then base64url-encoded (no padding). The signature is an EIP-191 signature over the ASCII bytes of the base64url string.
In practice a builder does not build these requests by hand — the Vana SDK signs them and handles the paid-read challenge. See the Build a Vana App guide.

Verification

When the Personal Server receives a builder request, it:
  1. Recovers the signer address from the Authorization header
  2. Verifies the signer is a registered builder onchain
  3. Checks aud matches the server’s own origin
  4. Checks method and uri match the actual request
  5. Validates iat/exp are within the allowed skew window (e.g. 5 minutes)
  6. For data reads: verifies grantId exists onchain and the signer matches the grantee
  7. Confirms the requested scope is within the granted scopes
  8. Where fee gating is enabled, confirms the grant’s fee shows as paid (see Payments & fees)
  9. Logs the access

Access control summary

EndpointWho can call
POST /v1/data/{scope}User only
GET /v1/data, GET /v1/data/{scope}User or builder with valid grant
GET /v1/data/{scope}/versionsUser or builder with valid grant
DELETE /v1/data/{scope}User only
POST /v1/grants, GET /v1/grantsUser only
GET /v1/access-logsUser only

Reachability

A client-side Personal Server must be reachable from the internet for a builder to read from it. A desktop-bundled server is reachable while the app is open; when the app is closed, builder requests fail until it reopens. To expose it, Vana provides FRP tunneling (Fast Reverse Proxy): the app connects to proxy.server.vana.org and receives a public URL at {userId}.server.vana.org with automatic TLS. A self-hosted server (advanced users, run as a Docker container on their own infrastructure) controls its own URL and uptime.

Bring your own compute (future)

The forthcoming addition is bring your own compute: an option to run your Personal Server in a dedicated compute environment instead of on your own device — so a web user gets an always-available Personal Server without keeping a tab open or installing the desktop app. This is one of the products Open Data Labs will offer: a compute environment designed so that the user controls it and only the user can see the data. Data stays encrypted inside the environment, and the intended guarantee is that no one else — including ODL, which provides the environment — can see what runs in it or read the data. This rests on hardware-attested execution and PGE, both in active development.
Status. Live: the client-side Personal Server — bundled in the desktop app and running in a browser tab for the web, on a single SDK. Coming: bring your own compute, a user-controlled compute environment (an ODL product) where only the user can see the encrypted data.

Sync

When a user has multiple Personal Server instances, they stay synchronized through the storage backend and Data Registry. See Storage & Encryption — Data sync for the full sync model.

Local data hierarchy

Personal Server implementations that use a filesystem store the same directory layout:
~/.vana/
├── data/                       # Decrypted user data
│   ├── instagram/
│   │   ├── profile/
│   │   │   └── 2026-01-21T10-00-00Z.json
│   │   ├── posts/
│   │   └── likes/
│   ├── chatgpt/
│   │   └── conversations/
│   └── youtube/
│       ├── watch_history/
│       └── subscriptions/
├── logs/                       # Access logs (JSON lines, daily rotation)
│   └── access-2026-01-21.log
├── index.db                    # Local registry index (SQLite)
└── server.json                 # Server configuration
Files are named {YYYY-MM-DDTHH-mm-ssZ}.json using the collectedAt timestamp.