Repository navigation
docs: Add service-to-service API standards - #894
Merged
mike-gorman-bitwarden merged 53 commits intoOct 28, 2026
Merged
Conversation
Deploying contributing-docs with
|
| Latest commit: |
c0f5ba4
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a7768609.contributing-docs.pages.dev |
| Branch Preview URL: | https://docs-service-to-service-api.contributing-docs.pages.dev |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…API standards Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mike-gorman-bitwarden
force-pushed
the
docs/service-to-service-api-standards
branch
from
October 18, 2026 10:24
39e734e to
6a35bcf
Compare
This was referenced Oct 18, 2026
Reword every API standards page to match the Service-to-service API Standards page in Confluence, split across the existing topical pages. Where the two disagreed, the repo's rules are kept. - Answer anticipated questions in place with a new :::faq admonition - Collect sources and RFC departures on the index - Rename payload-shape, json-values, and methods to resource-fields, json, and verbs to match their titles
…ctions Rename resource-fields back to payload-shape, since the page covers the whole body and not only resource fields. Split it into envelope and resource fields sections, each with its own example, and move its FAQ answers into a section at the bottom.
Bring back changes made for reviewers on earlier API standards pull requests that were lost when aligning with Confluence. - Move "kebab" to the shared word list instead of inline ignores - Exclude the public API and external-standard APIs from scope - Encourage, rather than require, thinking in terms of resources - Clarify a subject can be a collection of resources - Say where create paths stop and allow sub-resource elements - Link operationId to the OpenAPI Specification
Move the API standards back under the existing Server Architecture section so the top level matches Getting Started, and restore that section and the ADR links to match main. - Reword the scope to acknowledge existing APIs predate the standards - Remove Sources and RFC departures from the index; credit each source on the page where it applies
Rename the section to "APIs" and list it first under Server Architecture to keep the sidebar alphabetical. Lead the scope with the APIs the standards cover, then list what they do not cover.
audreyality
reviewed
Oct 19, 2026
Member
There was a problem hiding this comment.
🎨 The category is very long. I'd consider whether introducing a second grouping, consistent with the TOC, would help with organizing.
Contributor
Author
There was a problem hiding this comment.
Sorry, I don't know what you mean by "The category is very long."
Contributor
Author
There was a problem hiding this comment.
Do you mean the child pages?
Member
There was a problem hiding this comment.
Yeah, the page list within the "apis" category has a ton of entries in it. It would be helpful if the grouping in the sidebar reflected the grouping in the index.
mzieniukbw
reviewed
Oct 20, 2026
theMickster
reviewed
Oct 23, 2026
theMickster
reviewed
Oct 23, 2026
Removes the now unused faq admonition.
theMickster
reviewed
Oct 23, 2026
Uses creationDate, revisionDate, and deletedDate to match existing Bitwarden APIs.
Applies a suggestion from code review.
This reverts commit 608dfc8.
mzieniukbw
reviewed
Oct 24, 2026
Applies a suggestion from code review.
Applies a suggestion from code review.
audreyality
reviewed
Oct 27, 2026
withinfocus
approved these changes
Oct 28, 2026
withinfocus
left a comment
Contributor
There was a problem hiding this comment.
A great first version of this!
mike-gorman-bitwarden
deleted the
docs/service-to-service-api-standards
branch
October 28, 2026 12:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎟️ Tracking
Follow-up to ADR-0036 (#865).
📔 Objective
Adds the service-to-service API standards under Server Architecture: an index page that links to one page per topic, covering contracts, payloads, creating, reading, updating, deleting, acting upon, and bulk processing resources.
What's different
If you have worked on the existing
Apiserver, here is what changes when you build or call an APIthat follows these standards. Comparisons are taken from the
ApiOpenAPI specs (internal: 632operations; public: 28 operations). The standards apply only to new service-to-service APIs in new
services. Nothing existing is changing.
At a glance
/ciphers/{id})./api/v1/users/{id}), with rules for breaking changes andDeprecation/Sunsetheaders.{orgId}(/organizations/{orgId}/users)./api/v1/users).POSToften stands in for other verbs: 46 paths delete throughPOST/PUT .../delete, and 36 paths accept bothPUTandPOST.DELETEdeletes,PUTreplaces. Anything else is an action (POST .../{id}/actions/{action}) or a bulk operation (POST ...:bulk-delete).objecttype string ("object": "cipher").dataenvelope withid,type, andattributes; metadata inmeta.ErrorResponseModel: onemessageplus avalidationErrorsmap, returned as400.errorsarray; each error has a stablecode,status,title,detail,id, and asourcenaming the field, parameter, or header. Validation failures are422.2has to be looked up.CONFIRMED), compared case-insensitively.creationDate,revisionDate,organizationId,isTrusted.createdAt,updatedAt,createdBy; noIdsuffix for references; noisprefix for booleans.lastKnownRevisionDateon cipher updates.versionfield on resources that detect conflicts; a staleversionreturns409.Example: reading many resources
Most list endpoints today return everything in one response. Of the 69 internal
GETendpoints thatreturn a list, 12 accept a paging parameter, and 11 of those are event logs. Paging, where it
exists, uses an opaque
continuationTokenwith a fixed page size of 50 (only/notificationsaccepts a
pageSize). There are no totals, and filtering and sorting are not standardized: eachendpoint defines its own parameters, such as
start,end,status, orincludeGroups.Today: list an organization's members. Every member comes back in one response.
{ "object": "list", "data": [ { "object": "organizationUserUserDetails", "id": "…", "email": "alice@example.com", "status": 2 } ], "continuationToken": null }With the standards: the same request, paged, filtered, and sorted with standard parameters. The
organization comes from the request context.
{ "data": [ { "attributes": { "email": "alice@example.com", "status": "CONFIRMED" }, "id": "…", "type": "user" } ], "meta": { "pageCount": 9, "pageNumber": 1, "pageSize": 50, "totalCount": 402 } }What changes for you:
SHOULDpage. The caller chooses the page size, up to amaximum the API documents.
page[number],page[size]) can report page and totalcounts. Cursor paging (
page[size],page[after]) works like today's continuation token, butmetasays explicitly whether more results follow (hasMore) instead of leaving the caller toinfer it from a null token.
filter[{field}]with wildcards, multiple values, andranges;
sort=-createdAt; andfields=email,statusto return only some fields. The OpenAPI speclists which fields support each.
POST /api/v1/users:searchtakes a JSON Logic expression forAND/ORcombinations that do not fit in a URL, and returns the same shape as a read-manyrequest.
does not support returns
422, so a caller never silently receives unfiltered or unsorted data.What does not change
meant to be produced by
Bitwarden.Server.Sdkrather than written by hand.