bitwarden/server
Api
Active contributors: vault, admin-console, billing, tools, key-management, dirt, auth, secrets-manager, platform teams.
Purpose
src/Api/ is the main REST API that every Bitwarden client talks to. After a client obtains a JWT from the Identity host, every authenticated read or write goes here: vault items, organizations, sends, attachments, devices, account settings, billing self-service, secrets-manager resources, and the public API surface for organisations.
Directory layout
src/Api/
├── Program.cs / Startup.cs # Bootstraps + ConfigureServices/Configure pipeline
├── Controllers/ # Cross-cutting: ConfigController, DevicesController, InfoController, SettingsController
├── AdminConsole/ # Org / member / group / policy / provider / public-API controllers
│ ├── Controllers/
│ ├── Models/{Request,Response}/
│ ├── Authorization/ # Resource-based authz handlers
│ ├── Jobs/ # AC-specific Quartz jobs
│ └── Public/ # The /public/* org-level v1 API
├── Auth/ # AuthRequests, EmergencyAccess, master-password, WebAuthn, two-factor
├── Billing/ # User + org billing endpoints (subscribe, invoice, payment method)
├── Dirt/ # Reports, password-health, breach
├── KeyManagement/ # User key, key rotation validators
├── NotificationCenter/ # In-product notifications API
├── Platform/ # Installations, server config
├── SecretsManager/ # Projects, Secrets, ServiceAccounts, AccessPolicies
├── Tools/ # Sends, imports, send-access
├── Vault/ # Ciphers, Folders, Collections, Attachments, Sync
│ └── Controllers/CiphersController.cs # 1,713 lines — the big one
├── Utilities/ # Filters, attributes, model helpers
├── Jobs/ # JobsHostedService + cross-cutting Quartz jobs
├── Models/{Request,Response}/ # Cross-cutting shared models
├── appsettings.{Development,Production,QA,SelfHosted}.json
├── Dockerfile / build.sh / build.ps1 / entrypoint.sh
└── runtimeconfig.template.jsonKey abstractions
| Type | Path | Description |
|---|---|---|
Startup |
src/Api/Startup.cs |
Wires every service binding (database repositories, identity auth, billing, send / import / reports / event integrations, MVC + Swagger). |
CiphersController |
src/Api/Vault/Controllers/CiphersController.cs |
1,713 lines covering cipher CRUD, sharing, attachments, restore/delete. |
OrganizationsController |
src/Api/AdminConsole/Controllers/OrganizationsController.cs |
Org create / update / license / leave / sponsor / verify-domain. |
AccountsController |
src/Api/Auth/Controllers/AccountsController.cs |
Personal account: register, profile, security keys, premium upgrade, key rotation. |
SyncController |
src/Api/Vault/Controllers/SyncController.cs |
The GET /sync endpoint that returns the user + ciphers + folders + sends + orgs in a single payload. |
PublicControllers |
src/Api/AdminConsole/Public/Controllers/ |
The org-level v1 API (members, groups, collections, events, policies). Documented as Swagger group Public. |
ApiExceptionFilterAttribute |
src/Api/Utilities/ApiExceptionFilterAttribute.cs |
Maps Bit.Core.Exceptions.* to consistent JSON error bodies. |
JobsHostedService |
src/Api/Jobs/JobsHostedService.cs |
Registers per-app Quartz jobs (e.g. EmergencyAccessNotificationJob, OrganizationDomainVerificationJob). |
How it works
Authenticated request flow:
sequenceDiagram
participant Client
participant Api
participant DB
participant Bus
participant Notif as Notifications
Client->>Api: POST /ciphers (Bearer JWT)
Api->>Api: AddIdentityAuthenticationServices verifies JWT
Api->>Api: CurrentContextMiddleware loads ICurrentContext
Api->>DB: ICipherRepository.CreateAsync()
Api->>Bus: IEventService.LogCipherEventAsync (queue)
Api->>Notif: IPushNotificationService.PushSyncCipherUpdate
Api-->>Client: 200 OK CipherResponseModelICurrentContext is the per-request bag of facts about the caller — user id, organizations they belong to, device-trust state, scopes, IP. Every authorization handler reads from it.
Authorization is split:
- Policy-based — JWT scope:
Policies.Application(regular client),Policies.Web(web vault),Policies.Push(mobile push),Policies.Organization(org-bearer),Policies.Installation(self-host installation token),Policies.Secrets(Secrets Manager-only token),Policies.Send(send-access). - Resource-based — handlers under
src/Api/AdminConsole/Authorization/,src/Core/Vault/AuthorizationHandlers/,src/Core/SecretsManager/AuthorizationRequirements/, etc. Use[Authorize<TRequirement>]orIAuthorizationService.AuthorizeAsync.
Services registered
Startup.ConfigureServices registers the cross-cutting bundles:
services.AddBaseServices(globalSettings);
services.AddDefaultServices(globalSettings);
services.AddOrganizationSubscriptionServices();
services.AddCoreLocalizationServices();
services.AddBillingOperations();
services.AddReportingServices(globalSettings);
services.AddImportServices();
services.AddSendServices();
services.AddAuthorizationHandlers();
services.AddEventIntegrationsCommandsQueries(globalSettings);
services.AddSlackService(globalSettings);
services.AddTeamsService(globalSettings);The #if !OSS block additionally registers Commercial.Core.SecretsManager, Commercial.Infrastructure.EntityFramework.SecretsManager, and the secrets-manager Quartz jobs.
Integration points
- Identity — JWT validation via
services.AddIdentityAuthenticationServices(...). The Bearer token is issued by the Identity host. - Database — every repository interface in
src/Core/<Domain>/Repositories/is registered against either Dapper (src/Infrastructure.Dapper/) or EF (src/Infrastructure.EntityFramework/). - Push (Notifications) —
IPushNotificationServicecallsNotificationsover an internal HTTP / SignalR contract. - Events —
IEventServiceposts to a queue (Eventsingest) whichEventsProcessordrains. - Stripe / Braintree / PayPal — billing self-service goes through
IPaymentServiceandIStripePaymentService(src/Core/Billing/Services/). - Mail — transactional emails via
IMailService/HandlebarsMailService. - Application cache —
ApplicationCacheHostedServicelistens on the Service Bus topic to invalidate per-host caches when an org's settings change.
Public vs. internal API
Most endpoints are internal (consumed by Bitwarden's first-party clients). The Public/ namespace under src/Api/AdminConsole/Public/ exposes a documented, versioned org-management API. The PublicApiControllersModelConvention (src/Api/Utilities/) tags those controllers so they go into a separate Swagger group; the OAuth flow uses the api.organization scope.
Entry points for modification
- Adding a new vault endpoint? Edit
src/Api/Vault/Controllers/CiphersController.cs(or split a new controller) and add a domain command/query undersrc/Core/Vault/CommandsorQueries. See features/vault-and-ciphers. - Adding a new org endpoint? Choose the right controller under
src/Api/AdminConsole/Controllers/. If it should be exposed publicly, add it undersrc/Api/AdminConsole/Public/Controllers/and tag with thePublicAPI group. - Adding a billing self-service action? See
src/Api/Billing/Controllers/plussrc/Core/Billing/Commandsand the correspondingIPaymentServicemethod. - Tightening authorization? Add or extend an
IAuthorizationHandlerin the relevantAuthorizationHandlers/folder rather than embedding the check in the controller.
For the OAuth side of things, see identity. For background events, see events and events-processor.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.