# How Vaultwarden Implements the Bitwarden Client API: Supported Endpoints and Architecture

> Discover how Vaultwarden upholds Bitwarden client API compatibility. Explore supported endpoints and Rust Rocket architecture for seamless syncing and ciphers management.

- Repository: [Daniel García/vaultwarden](https://github.com/dani-garcia/vaultwarden)
- Tags: internals
- Published: 2026-03-07

---

**Vaultwarden implements the Bitwarden client API using the Rocket web framework in Rust, exposing REST endpoints under `src/api` that handle sync, ciphers, folders, and identity services while maintaining full compatibility with official Bitwarden clients.**

Vaultwarden is a self-hosted, Rust-based implementation of the Bitwarden server API that allows users to run their own password management backend. Understanding how vaultwarden implements the Bitwarden client API reveals a lightweight yet comprehensive architecture that mirrors the official server behavior. This article examines the supported endpoints, request flow, and key source files in the `dani-garcia/vaultwarden` repository.

## Architectural Overview

Vaultwarden uses the **Rocket** web framework to expose HTTP routes that correspond directly to Bitwarden client-side REST endpoints. The architecture follows a modular design where route definitions, business logic, and data models are cleanly separated.

### Web Server and Route Registration

In [`src/main.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/main.rs), the application launches the Rocket server and mounts all API routes returned by `api::routes()`. The top-level [`src/api/mod.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/mod.rs) aggregates route objects from sub-modules and returns them to Rocket for registration.

```rust
// src/api/mod.rs - Route aggregation pattern
pub fn routes() -> Vec<Route> {
    let mut routes = Vec::new();
    routes.append(&mut core::routes());
    routes.append(&mut identity::routes());
    // ... additional modules
    routes
}

```

Each endpoint is defined using Rocket attribute macros (`#[get]`, `#[post]`, `#[put]`, `#[delete]`) in sub-modules under `src/api/core/`. The [`src/api/core/mod.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/mod.rs) file collects routes from ciphers, folders, organizations, and other domains into a unified vector.

### Authentication and Headers

The `auth::Headers` struct in [`src/auth.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/auth.rs) extracts the `Authorization: Bearer <token>` header and validates the user session before any business logic executes. This provides handlers with an authenticated `User` object and request metadata including host, device type, and IP address.

```rust
// Handlers receive pre-validated authentication context
#[get("/ciphers/<id>")]
fn get_cipher(id: CipherId, headers: Headers) -> JsonResult {
    // headers.user is already authenticated
}

```

## Supported API Endpoints

Vaultwarden mirrors the full Bitwarden API surface, implementing endpoints across several functional categories. All routes return JSON responses structured exactly as official Bitwarden clients expect.

### Sync and Data Retrieval

The sync endpoint aggregates all user data into a single response. Located in [`src/api/core/ciphers.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/ciphers.rs), the `sync` function (lines 16-20) collects the user profile, folders, collections, ciphers, sends, policies, and domains.

- **Method**: `GET`
- **Route**: `/api/sync`
- **Handler**: `sync`
- **Source**: [`src/api/core/ciphers.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/ciphers.rs)

### Cipher Management

Ciphers (encrypted password entries) support full CRUD operations plus sharing and attachments. The [`src/api/core/ciphers.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/ciphers.rs) file contains the primary implementation with handlers including:

- **`get_ciphers`** (lines 200-207): Lists all accessible ciphers via `GET /ciphers`
- **`post_ciphers`** (lines 52-57): Creates new ciphers via `POST /ciphers`
- **`put_cipher`** (lines 68-73): Updates existing ciphers via `PUT /ciphers/<id>`
- **`post_cipher_share`** (lines 334-339): Shares ciphers with collections via `POST /ciphers/<id>/share`
- **`delete_cipher`** (lines 76-84): Removes ciphers via `DELETE /ciphers/<id>`

Attachment handling uses a two-step v2 API: `post_attachment_v2` creates the metadata record, while `post_attachment_v2_data` receives the actual file upload.

### Folders, Collections, and Organizations

Folder management resides in [`src/api/core/folders.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/folders.rs) with endpoints for listing (`get_folders`) and creating (`post_folders`). Organization and collection logic appears in [`src/api/core/organizations.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/organizations.rs), including:

- **`get_collections`** (lines 853-860): Retrieves organization collections
- **`post_collections_update`**: Updates cipher collection memberships

The "Send" feature (secure file sharing) is implemented in [`src/api/core/sends.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/sends.rs) with `get_sends` and `post_sends` handlers.

### Identity and Authentication

The OAuth-style token endpoint lives in [`src/api/identity.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/identity.rs). The **`post_token`** handler processes `POST /connect/token` requests, handling password grants, refresh tokens, and device authorization.

### Real-Time Notifications

After data mutations, handlers call `Notify::send_*` methods to push updates via WebSockets. The **`ws_hub`** handler in [`src/api/notifications.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/notifications.rs) manages the `GET /notifications/hub` WebSocket connection for live client synchronization.

## Request Lifecycle

Understanding how vaultwarden implements the Bitwarden client API requires examining the request flow:

1. **Route Matching**: Rocket matches the URL to an attribute macro like `#[get("/ciphers/<cipher_id>")]`
2. **Parameter Parsing**: Path and query parameters convert to typed arguments (e.g., `cipher_id: CipherId`)
3. **Authentication**: The `Headers` guard extracts and validates the bearer token, supplying the `User` object
4. **Authorization**: Business logic checks permissions using model methods like `cipher.is_write_accessible_to_user`
5. **Response Building**: Handlers use `serde_json::json!` and model `to_json` methods to format responses
6. **Push Notification**: After mutations, `Notify` triggers WebSocket updates through the notifications service

## Practical API Examples

### Sync All Client Data

```bash
curl -s -H "Authorization: Bearer $TOKEN" \
     -H "User-Agent: Bitwarden/2025.12.0" \
     "$BASE_URL/api/sync"

```

This calls the `sync` function in [`src/api/core/ciphers.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/ciphers.rs), returning a JSON object with `"object":"sync"` containing all user vault data.

### Create a New Login Cipher

```bash
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
           "type":1,
           "name":"My Site",
           "login":{"username":"alice","password":"s3cr3t"},
           "folderId":null
         }' \
     "$BASE_URL/api/ciphers"

```

The `post_ciphers` handler parses `CipherData`, invokes `Cipher::new`, and delegates to `update_cipher_from_data` for validation and persistence.

### Upload an Attachment (v2 API)

Step 1: Request upload URL via `post_attachment_v2`:

```bash
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"key":"<encrypted-key>","file_name":"secret.pdf","file_size":12345}' \
     "$BASE_URL/api/ciphers/<cipher_id>/attachment/v2"

```

Step 2: Upload file data via `post_attachment_v2_data`:

```bash
curl -X POST -F "data=@secret.pdf" \
     "$BASE_URL/api/ciphers/<cipher_id>/attachment/<attachment_id>"

```

### Share a Cipher with Collections

```bash
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"ciphers":[{"id":"<cipher-id>"}],"collectionIds":["<collection-id>"]}' \
     "$BASE_URL/api/ciphers/share"

```

This invokes `put_cipher_share_selected`, which iterates through ciphers and calls `share_cipher_by_uuid` to update the `CollectionCipher` join table after validating permissions.

## Summary

- **Vaultwarden uses the Rocket framework** to register REST routes in [`src/api/mod.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/mod.rs) and [`src/api/core/mod.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/mod.rs), mounting them in [`src/main.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/main.rs).
- **Core endpoints** cover sync (`/api/sync`), cipher CRUD (`/api/ciphers/*`), folders (`/api/folders`), organizations (`/api/organizations`), and sends (`/api/sends`).
- **Authentication** occurs through the `auth::Headers` guard in [`src/auth.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/auth.rs), which validates bearer tokens before handlers execute.
- **Real-time updates** flow through the WebSocket hub in [`src/api/notifications.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/notifications.rs), triggered by `Notify` calls after data mutations.
- **File attachments** use a two-step v2 API process defined in [`src/api/core/ciphers.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/ciphers.rs) for metadata creation and binary upload.

## Frequently Asked Questions

### How does Vaultwarden handle authentication for API requests?

Vaultwarden validates bearer tokens through the `auth::Headers` struct defined in [`src/auth.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/auth.rs). This guard extracts the `Authorization` header, validates the JWT token against the database, and injects the authenticated `User` object directly into route handlers. The system supports standard Bitwarden authentication flows including password grants and refresh tokens via the `post_token` handler in [`src/api/identity.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/identity.rs).

### Which Bitwarden client features are not supported by Vaultwarden?

While Vaultwarden implements the vast majority of client-facing endpoints including sync, ciphers, folders, collections, sends, emergency access, and attachments, certain enterprise features may differ from the official cloud implementation. The repository tracks upstream Bitwarden versions (currently 2025.12.0) and implements features selectively based on self-hosted use cases. Specific enterprise policies and advanced administrative features may have limited support compared to the official Bitwarden server.

### How does Vaultwarden push real-time updates to connected clients?

After any data mutation (creating, updating, or deleting ciphers), handlers invoke methods on the `Notify` struct to broadcast changes. The `ws_hub` handler in [`src/api/notifications.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/notifications.rs) manages WebSocket connections at `GET /notifications/hub`, maintaining persistent connections to clients and pushing JSON payloads that trigger client-side vault refreshes without requiring manual sync requests.

### Where is the cipher sharing logic implemented in the source code?

Cipher sharing functionality resides in [`src/api/core/ciphers.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/api/core/ciphers.rs). The `put_cipher_share_selected` handler processes `POST /api/ciphers/share` requests, while `share_cipher_by_uuid` contains the core logic for validating collection permissions and updating the `CollectionCipher` join table. These functions ensure users can only share ciphers with collections where they have appropriate write access.