Skip to main content
Version: Next

Vaults & Records API

The vaults and records API is the core data layer of SyVault. All record payloads are encrypted client-side before transmission; the server stores and returns opaque ciphertext.

Authentication

All endpoints require a valid access token in the Authorization header:

Authorization: Bearer <access_token>

Vaults

List vaults

Returns all vaults the authenticated user has access to. When Travel Mode is active, vaults not marked as safe-for-travel are excluded from the response.

GET /api/vaults
curl https://vault.example.com/api/vaults \
-H "Authorization: Bearer $TOKEN"

Response:

{
"data": [
{
"id": "vault-uuid-1",
"name": "Personal",
"type": "personal",
"created_at": "2025-08-15T10:30:00Z",
"updated_at": "2026-04-05T14:22:00Z",
"record_count": 47,
"safe_for_travel": true
},
{
"id": "vault-uuid-2",
"name": "Work",
"type": "shared",
"created_at": "2025-09-01T08:00:00Z",
"updated_at": "2026-04-04T09:15:00Z",
"record_count": 132,
"safe_for_travel": false
}
]
}

Create a vault

POST /api/vaults
curl -X POST https://vault.example.com/api/vaults \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Side Project",
"type": "personal",
"encrypted_key": "base64-vault-encryption-key"
}'

Response (201):

{
"id": "vault-uuid-3",
"name": "Side Project",
"type": "personal",
"created_at": "2026-04-06T12:00:00Z",
"record_count": 0,
"safe_for_travel": false
}

Delete a vault

DELETE /api/vaults/{id}
curl -X DELETE https://vault.example.com/api/vaults/vault-uuid-3 \
-H "Authorization: Bearer $TOKEN"

Returns 204 No Content on success. All records inside the vault are permanently deleted.

Records

List records in a vault

GET /api/vaults/{id}/records
curl https://vault.example.com/api/vaults/vault-uuid-1/records \
-H "Authorization: Bearer $TOKEN"

Response:

{
"data": [
{
"id": "record-uuid-1",
"vault_id": "vault-uuid-1",
"type": "login",
"encrypted_data": "base64-encrypted-payload",
"created_at": "2025-10-01T12:00:00Z",
"updated_at": "2026-04-01T08:30:00Z"
},
{
"id": "record-uuid-2",
"vault_id": "vault-uuid-1",
"type": "secure_note",
"encrypted_data": "base64-encrypted-payload",
"created_at": "2025-11-15T09:00:00Z",
"updated_at": "2025-11-15T09:00:00Z"
}
]
}

The encrypted_data field contains the AES-256-GCM encrypted JSON payload. The client decrypts it using the vault's encryption key.

Create a record

POST /api/vaults/{id}/records
curl -X POST https://vault.example.com/api/vaults/vault-uuid-1/records \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "login",
"encrypted_data": "base64-encrypted-payload"
}'

The encrypted_data must be encrypted client-side before sending. A typical decrypted payload looks like:

{
"name": "GitHub",
"username": "alice",
"password": "hunter2",
"uri": "https://github.com/login",
"notes": "Personal account",
"totp_secret": "JBSWY3DPEHPK3PXP"
}

Response (201):

{
"id": "record-uuid-new",
"vault_id": "vault-uuid-1",
"type": "login",
"encrypted_data": "base64-encrypted-payload",
"created_at": "2026-04-06T12:05:00Z",
"updated_at": "2026-04-06T12:05:00Z"
}

Update a record

PUT /api/vaults/{id}/records/{rid}
curl -X PUT https://vault.example.com/api/vaults/vault-uuid-1/records/record-uuid-1 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "login",
"encrypted_data": "base64-updated-encrypted-payload"
}'

Returns the updated record with a new updated_at timestamp.

Delete a record

DELETE /api/vaults/{id}/records/{rid}
curl -X DELETE https://vault.example.com/api/vaults/vault-uuid-1/records/record-uuid-1 \
-H "Authorization: Bearer $TOKEN"

Returns 204 No Content.

Batch import

Import up to 1000 records in a single request. Useful for migrations from other password managers.

POST /api/vaults/{id}/import
curl -X POST https://vault.example.com/api/vaults/vault-uuid-1/import \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"type": "login",
"encrypted_data": "base64-encrypted-1"
},
{
"type": "login",
"encrypted_data": "base64-encrypted-2"
}
]
}'

Response (201):

{
"imported": 2,
"failed": 0,
"records": [
{"id": "record-uuid-a", "type": "login"},
{"id": "record-uuid-b", "type": "login"}
]
}

The maximum batch size is 1000 records. Requests exceeding this limit receive a 413 Payload Too Large response.

Error Responses

StatusMeaning
400Invalid request body or missing fields
401Missing or expired access token
403No access to the specified vault
404Vault or record not found
413Import batch exceeds 1000 records
429Rate limited