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
| Status | Meaning |
|---|---|
400 | Invalid request body or missing fields |
401 | Missing or expired access token |
403 | No access to the specified vault |
404 | Vault or record not found |
413 | Import batch exceeds 1000 records |
429 | Rate limited |