VESvault REST API
The VESvault REST API at
https://api.ves.host/v1/
stores and shares encryption keys.
It is the API that
libVES.js,
libVES.c
and the
ves utility call.
All encryption happens in the client. The API stores public keys, encrypted private keys and encrypted values,
and never receives a private key or a Vault Item value in the clear.
A client that writes keys or values has to do that encryption itself, exactly as libVES does –
so for anything that creates, unlocks or shares keys, use libVES.
This page describes the request and response format, the objects, and the parts of the API that are useful
on their own: reading objects, paging through lists and watching for changes.
Errors are listed in
VESvault API Error Numbers.
Requests
https://api.ves.host/v1/
Base URL
All requests.
https://poll.ves.host/v1/
Base URL
The same API, for requests that wait for changes.
The path is a collection, optionally followed by an object ID: vaultKeys/654321
.
The collections are users
, vaultKeys
, vaultItems
, files
, externals
,
domains
, events
and sessions
, plus:
me
User
The user of the current session.
attn
Object
vaultKeys
that need the user's action, such as a temp key to rekey or a recovery in progress.
logout
Ends the current session.
GET
Method
Read an object.
POST
Method
Find, create or change objects. The body is JSON – see Writing.
PUT
Method
Update the object in the path.
DELETE
Method
Delete the object in the path.
GET https://api.ves.host/v1/me?fields=id,email,currentVaultKey(id,type,algo)
Authorization: Bearer session-token
Responses
Every response is a JSON object. The requested object is in result
:
{
"result": {
"id": 123456,
"email": "alice@example.com",
"firstName": "Alice",
"lastName": "Example",
"currentVaultKey": {
"id": 654321,
"type": "current",
"algo": "ECDH"
}
}
}
result
Object
The object, with the fields the session may read.
- IDs are positive integers, sent as JSON numbers.
- Dates are UTC, ISO 8601, with an optional fraction of a second:
2026-11-02T14:05:09Z
.
- A response can include fields that were not asked for. Ignore them.
- The
X-VES-Server
response header names the server version. Include it when you report a problem.
A field the session is not allowed to read is left out of the result, exactly like a field with no value.
An absent field can mean either. An empty list ([]
) means the list is readable and has no entries.
Authentication
A request carries a session token in the Authorization
header:
Authorization: Bearer session-token
Session tokens come from libVES. When an app unlocks a vault with libVES.js or libVES.c,
the library obtains a session token and sends it with every call.
The server issues each token encrypted to a Vault Key, so only a client that can unlock that key can use it.
- A token stops working when it expires or after
logout
. Errors 3014
and 3015 mean the vault has to be unlocked again.
- A Bearer value that starts with
~
is a verify token: read-only access to one Vault Item or File,
given to a third party to prove access. See VESauth.
- A request with no
Authorization
header runs without a session and sees only public data,
such as the active Vault Keys a user can be shared with.
- HTTP Basic authorization is part of the VESvault sign-in flow and is not covered here.
Objects
Each object is listed with its path and its main fields. Objects have other fields, used by libVES.
Which fields a session can read depends on how it relates to the object.
User (users/id, me)
A VESvault account. me
is the user of the current session.
id
Integer
The user ID.
email
String
The account email address.
firstName
String
lastName
String
currentVaultKey
Vault Key
The Primary Vault Key, type current
.
shadowVaultKey
Vault Key
The VESrecovery key, type shadow
.
activeVaultKeys
Array(Vault Key)
The keys others share with: the current and shadow keys.
vaultKeys
Array(Vault Key)
Every key of the account, including secondary and deleted keys.
events
Array(Event)
The account's event log.
createdAt
Date
updatedAt
Date
Vault Key (vaultKeys/id)
A key pair. The public key is stored as is; the private key only in encrypted form.
id
Integer
The Vault Key ID.
algo
String
The key algorithm: ECDH
, RSA
or OQS
(post-quantum).
publicKey
String
The public key, PEM.
privateKey
String
The private key, encrypted on the client with the key's passphrase (its VESkey) before it was sent.
user
User
The owner.
creator
User
For a temp
key, the user who created it.
externals
Array(External)
For a secondary
key, the app domain and external ID that name the vault.
vaultEntries
Array(Vault Entry)
One entry for every Vault Item shared with this key.
vaultItems
Array(Vault Item)
Items that belong to the key itself, such as a temp key's passphrase or recovery tokens. Items shared with the key are under vaultEntries
.
events
Array(Event)
The key's event log.
createdAt
Date
updatedAt
Date
Key types:
current
The Primary Vault Key. One per account; its passphrase is the user's primary VESkey.
shadow
The key VESrecovery restores access with. One per account.
recovery
A shadow key whose recovery is in progress.
secondary
An App Vault key, named by an External. Its VESkey is kept as a Vault Item in the owner's Primary Vault.
temp
A key created by another user for someone who has no suitable key yet, so that items can be shared with them. Rekeyed later and deleted.
lost
A former current key whose VESkey the user has lost.
pending
Reserved for background operations.
deleted
A deleted key.
Vault Item (vaultItems/id)
A secret value, such as a file encryption key or a password, shared with one or more Vault Keys. An item belongs either to a File or to a Vault Key.
id
Integer
The Vault Item ID.
type
String
string
, file
, password
or secret
.
file
File
The File the item belongs to.
vaultKey
Vault Key
The Vault Key the item belongs to.
vaultEntries
Array(Vault Entry)
One entry for every Vault Key the item is shared with.
meta
Object
Application metadata, any JSON. Stored unencrypted – never put secrets here.
deleted
Boolean
The item has been deleted.
verifyToken
String
A token that proves access to this item to a third party. See VESauth.
events
Array(Event)
The item's event log.
createdAt
Date
updatedAt
Date
Vault Entry (no path of its own)
One Vault Item shared with one Vault Key. Reached through vaultEntries
on an item or a key.
id
Integer
The Vault Entry ID.
vaultItem
Vault Item
vaultKey
Vault Key
encData
String
The item's value, encrypted to this key's public key. Base64.
File (files/id)
A named object in an app domain, addressed as //domain/externalId
. Its Vault Item holds the secret for it, such as a file's encryption key.
id
Integer
The File ID.
externals
Array(External)
The domain and external ID that name the file.
vaultItem
Vault Item
The item holding the secret.
name
String
An optional file name.
path
String
An optional path.
creator
User
The user who created the file.
verifyToken
String
As on a Vault Item.
External (externals/id)
A name in an app domain: the domain, externalId
pair that addresses an App Vault or a File.
id
Integer
The External ID.
domain
Domain
externalId
String
The name within the domain.
vaultKey
Array(Vault Key)
The App Vault key the name points to.
Domain (domains/id, domains/name)
An app domain. Visible to the domain's own sessions and to its creator.
id
Integer
The Domain ID.
name
String
description
String
url
String
tags
Array
The names the domain is known by.
creator
User
vaultKeys
Array(Vault Key)
The App Vault keys in the domain.
vaultItems
Array(Vault Item)
The items in the domain.
externals
Array(External)
The names in the domain.
events
Array(Event)
The domain's event log.
createdAt
Date
updatedAt
Date
Event (events/id)
One entry in an event log.
id
Integer
The Event ID. Event IDs increase over time.
recordedAt
Date
user
User
The user the event is about.
creator
User
vaultKey
Vault Key
The key the event is about, where there is one.
vaultItem
Vault Item
The item the event is about, where there is one.
vaultEntry
Vault Entry
For vaultEntry.*
events.
session
Session
For session.*
events.
authorSession
Session
The session that made the change.
Event types: user.created
, user.updated
, user.pending
, vaultKey.created
, vaultKey.deleted
, vaultKey.lost
, vaultKey.listening
, vaultKey.pending
, vaultItem.created
, vaultItem.updated
, vaultItem.deleted
, vaultItem.listening
, vaultEntry.created
, vaultEntry.deleted
, session.created
, session.updated
.
More types may be added.
Session (sessions/id)
A session opened with a session token.
id
Integer
The Session ID.
user
User
vaultKey
Vault Key
The key the session was opened with, where there is one.
domain
Domain
createdAt
Date
expiresAt
Date
accessAt
Date
The last time the session was used, approximately.
remote
String
The client's IP address.
userAgent
String
The client's User-Agent.
Selecting Fields
The fields
parameter names the fields to return. Names are separated by commas.
The fields of a related object or a list go in parentheses after its name:
GET https://api.ves.host/v1/vaultItems/777?fields=id,type,meta,vaultEntries(vaultKey(id,type,user(email)))
- A name the object does not have is ignored, without an error. If a field is missing, check its spelling.
- Nesting is limited to 8 levels, counting the requested object (2071).
- Without
fields
, the response holds a few identifying fields only.
- Encode
+
as %2B
in a range – an unencoded +
in a URL reads as a space.
libVES also encodes [
and ]
as %5B
and %5D
.
Lists and Ranges
Lists are returned in ID order. A list without a range is returned whole, up to a limit set by the server;
a longer list answers
9011 (HTTP 507) with the first part of the list.
The
limit
parameter lowers that limit for one request.
To read a list in pages, put a range after it in fields
: [start+count]
, as in
events(id,type)[0+100]
.
start
is an object ID, not a position: the list returns up to count
objects whose ID is
start
or higher, and 0
starts from the beginning.
[start-count]
goes the other way, from start
down ([0-100]
is the 100 highest IDs).
The response carries one ranges
entry for each ranged list:
"ranges": [
{ "path": ["events"], "returned": 100, "more": true, "nextId": 18234 }
]
path
Array
The list, as field names from the requested object.
returned
Integer
How many entries this page holds.
more
Boolean
The page is full, so there may be more. false
means the list has ended.
nextId
Integer
The start
for the next page, in the same direction.
Watching for Changes
Users, Vault Keys, Vault Items and Domains have event logs (events
).
To wait for new events, ask for the events from the next ID you expect, and add poll
:
GET https://poll.ves.host/v1/vaultKeys/654321?fields=events(id,type,recordedAt)%5B18234%2B100%5D&poll=60
If there are events from that ID on, the API returns them at once.
If not, it holds the request for up to
poll
seconds (at most 120), returns soon after an event is recorded,
or returns an empty list when the time runs out. Then ask again from
nextId
.
A Domain's
vaultItems
and
externals
lists can be watched the same way.
libVES.js does this for you.
Writing
A POST sends one object as JSON. Each key is a field; related objects and lists nest inside it.
The response is the resulting object, read back with fields
.
$op
on any object in the body says what to do with that object:
fetch
$op
Find an existing object by the fields given, and change nothing. An error if there is none.
match
$op
Like fetch
, and the given fields must equal the stored ones.
create
$op
Create the object. An error if it exists.
update
$op
Change an existing object.
delete
$op
Delete the object. On a Vault Entry inside a Vault Item, stop sharing the item with that key.
ignore
$op
Refer to the object without changing it.
Without $op
, the API finds the object if it exists, creates it if not, and saves the fields that changed.
"$ref": "#/path"
stands for an object already given elsewhere in the same body.
For example, to look up an App Vault key by its name:
POST https://api.ves.host/v1/vaultKeys?fields=id,type,algo,publicKey
{ "$op": "fetch", "externals": [ { "domain": "demo", "externalId": "alice" } ] }
The API checks each change against the session's permissions and the state of the objects,
and rejects an invalid one with the error numbers in
VESvault API Error Numbers.
It cannot check the encrypted values themselves, which is why writes that carry keys or encrypted data are left to libVES.
Deleting a Vault Item or a Vault Key marks it as deleted. Accounts are not deleted through the API.
Limits
- Nesting: 8 levels of
fields
(2071).
- Size: a list longer than the server's limit, or a response too large to build,
answers HTTP 507 (9xxx). Ask for fewer fields or use a range.
- Quota: each request is charged against several budgets. When one runs out the API answers HTTP 503
(8xxx). Retry later, with an increasing delay.
What the Server Stores
Readable by the server:
account email addresses and names; public keys, key types and algorithms; domain names and external IDs;
Vault Item types and meta
; file names and paths; the event logs;
and session records with their times, the client's IP address and User-Agent.
Encrypted on the client:
Vault Item values, held as one Vault Entry per Vault Key, each encrypted to that key;
and private keys, encrypted with the key's passphrase.
VESkeys and private keys reach the server only in encrypted form.
Not stored: file contents. VESvault holds the key to a file, not the file.
Stability
- Paths under
/v1/
are stable.
- New fields, event types and error numbers may be added. Existing fields are not removed.
- Error numbers keep their meaning. Match on
number
or code
, never on the message.