Skip to main content
Adopt

IPA-117: Documentation

Documentation serves as a primary tool for clients to better understand an API and its functionality. Consistent documentation patterns across the API platform will promote clarity, completeness and consistency.

Guidance

Descriptions

  1. API producers must provide descriptions for properties, operations, parameters, and tags.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    description: Returns a single order by its unique identifier.
    parameters:
    - name: orderId
    in: path
    description: Unique identifier of the order to return.
    schema:
    type: string
    Why:

    The operation, the parameter, and (elsewhere) every property each carry a description, so a consumer reading the generated reference learns what each element is without inspecting the implementation.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    parameters:
    - name: orderId
    in: path
    schema:
    type: string
    Why:

    Neither the operation nor the parameter has a description, leaving a consumer to guess what the endpoint does and what orderId means.

  2. API producers may provide descriptions for schemas.

  3. Descriptions should be complete but brief. A good description aims to cover what the element is, how to use it, default values, optional or required behavior, and common errors.

    properties:
    status:
    type: string
    description: >-
    Current state of the order. Defaults to PENDING when an order is created.
    Transitions to SHIPPED once fulfillment begins and to CANCELED if the
    order is withdrawn before shipping.
    enum: [PENDING, SHIPPED, CANCELED]
    default: PENDING
    Why:

    The description names the field, its default, and the meaning of each state in a few sentences, so a consumer needs nothing else to use it correctly.

    properties:
    status:
    type: string
    description: The status.
    enum: [PENDING, SHIPPED, CANCELED]
    default: PENDING
    Why:

    The description restates the field name and omits the default and the meaning of each state, so it is brief but not complete.

    1. Collect every description on properties, operations, parameters, and tags.

    2. For each description, check that it covers the applicable facets: what the element is, how to use it, default value, whether it is optional or required, and common errors. Not every facet applies to every element.

    3. Confirm the description stays brief: a few sentences, no padding that merely restates the field name or type.

    4. Report descriptions that are empty of substance, that restate the name, or that omit an applicable facet such as a default value.

  4. Descriptions should avoid overly technical language and should prefer simple syntax that can easily be translated for non-English speakers.

    properties:
    retryCount:
    type: integer
    description: Number of times the job was retried after a failure.
    Why:

    Plain wording and a simple sentence convey the meaning to a non-specialist and translate cleanly.

    properties:
    retryCount:
    type: integer
    description: >-
    Cardinality of idempotent re-invocations dispatched by the orchestrator
    subsequent to a non-terminal fault condition.
    Why:

    Jargon and a dense clause obscure a simple idea and resist translation.

    1. Collect every description across the spec.
    2. Flag descriptions that rely on jargon, acronyms, or nested clauses where a plain sentence would convey the same meaning.

    3. Report descriptions that a non-native English reader, or a translation tool, would struggle to parse.

  5. Descriptions must avoid company internal language conventions.

    properties:
    ownerId:
    type: string
    description: Unique identifier of the user who owns this project.
    Why:

    The wording uses terms a public consumer understands rather than an internal codename or team-specific shorthand.

    properties:
    ownerId:
    type: string
    description: The principal ref from the legacy AuthZ blob, see PROJ-204.
    Why:

    Internal codenames, ticket numbers, and team jargon are meaningless to an external consumer and leak implementation context.

    1. Collect every description across the spec.
    2. Flag descriptions containing internal codenames, ticket references, team names, or shorthand that only an employee would recognize.

    3. Report each such description as a violation.
  6. Descriptions should describe fields in terms meaningful to API consumers, not in terms of API mechanics. Referencing other API-specific constructs couples the description to tooling context that is not visible to end users of generated clients and forces downstream tooling to override the text.

    properties:
    organizationId:
    type: string
    description: >-
    Unique 24-hexadecimal digit string that identifies the organization that
    contains the projects.
    Why:

    The description explains the field on its own terms, so it reads the same in a generated SDK as in the raw spec.

    properties:
    organizationId:
    type: string
    description: >-
    Unique 24-hexadecimal digit string that identifies the organization. Use
    the listOrganizations operation on the /orgs endpoint to retrieve all
    organizations to which the authenticated user has access.
    Why:

    Naming an operationId and endpoint path ties the text to API mechanics that a consumer of a generated client never sees, forcing tooling to rewrite the description.

    1. Collect every property description across the spec.

    2. Flag descriptions that reference operationIds, endpoint paths, or other spec-internal constructs instead of explaining the field in consumer terms.

    3. Report each such description so the API mechanics can be removed or moved to external documentation.

  7. When the same property appears in multiple polymorphic variants unified by oneOf with a discriminator (see IPA-125), that property's description should be identical across variants. Variant-specific context should be documented in the variant schema's own description, not by diverging the property's description between variants.

    components:
    schemas:
    CardPayment:
    type: object
    properties:
    amount:
    type: integer
    description: Total charged, in the smallest currency unit.
    BankPayment:
    type: object
    properties:
    amount:
    type: integer
    description: Total charged, in the smallest currency unit.
    Why:

    The shared amount property reads identically in every variant, so a consumer sees one consistent definition regardless of which variant is returned.

    components:
    schemas:
    CardPayment:
    type: object
    properties:
    amount:
    type: integer
    description: Total charged to the card, in the smallest currency unit.
    BankPayment:
    type: object
    properties:
    amount:
    type: integer
    description: Amount of the transfer in cents after fees are deducted.
    Why:

    The same property carries diverging descriptions across variants, so the generated docs show conflicting definitions for one field; the card-specific note belongs on the variant schema, not on amount.

    1. Find every oneOf with a discriminator and collect the variant schemas it unifies.

    2. Across those variants, group properties that share a name.

    3. For each shared property, compare its description across variants and flag any divergence.

    4. Report shared properties whose descriptions differ, and check that any variant-specific note lives on the variant schema's own description.

    Depends on

See Description Object.

Description Formatting

  1. Descriptions may use CommonMark.

  2. Descriptions must start with an uppercase letter.

    parameters:
    - name: status
    in: query
    description: Filter results by order status.
    schema:
    type: string
    Why:

    The description begins with a capital letter, matching prose conventions across the reference.

    parameters:
    - name: status
    in: query
    description: filter results by order status.
    schema:
    type: string
    Why:

    A lowercase opening reads as an unfinished fragment and breaks the consistent sentence style of the reference.

  3. Descriptions must end with a full stop (.).

    parameters:
    - name: status
    in: query
    description: Filter results by order status.
    schema:
    type: string
    Why:

    The terminating period marks the description as a complete sentence.

    parameters:
    - name: status
    in: query
    description: Filter results by order status
    schema:
    type: string
    Why:

    Without a final period the description reads as a truncated fragment and diverges from the rest of the reference.

  4. Descriptions must not use raw HTML.

    properties:
    notes:
    type: string
    description: |
    Free-form notes about the order. Supports the following:

    - shipping instructions
    - gift messages
    Why:

    CommonMark renders consistently across the tools that consume the spec, including generated client documentation.

    properties:
    notes:
    type: string
    description: >-
    Free-form notes about the order. Supports <ul><li>shipping
    instructions</li><li>gift messages</li></ul>.
    Why:

    Raw HTML tags are not rendered uniformly by spec tooling and often surface as literal text in generated clients.

  5. Descriptions should not include inline tables, as these may not work well with all tools and in particular generated client code. Consider using lists over tables; if a comprehensive description with tables is needed, prefer a short description plus externalDocs.

    properties:
    tier:
    type: string
    description: |
    Service tier for the account. Available tiers:

    - FREE: no monthly cost, limited quota
    - PRO: monthly cost, expanded quota
    Why:

    A short list conveys the same information as a table and renders reliably in generated client documentation.

    properties:
    tier:
    type: string
    description: |
    Service tier for the account.

    | Tier | Cost | Quota |
    | ---- | ------- | -------- |
    | FREE | none | limited |
    | PRO | monthly | expanded |
    Why:

    Inline tables are rendered inconsistently across tools and frequently collapse into unreadable text in generated clients.

Sensitive Field Markings

The OpenAPI format: password keyword identifies properties whose value is itself a secret. Guidelines below govern when to apply it.

  1. Must use format: password on any property whose value is itself a secret per IPA-111 — Sensitive Fields.

    components:
    schemas:
    ApiKey:
    type: object
    properties:
    key:
    type: string
    format: password
    writeOnly: true
    Why:

    The key property carries a secret value (an API key), so format: password marks it as a secret for tooling and consumers.

    components:
    schemas:
    ApiKey:
    type: object
    properties:
    key:
    type: string
    writeOnly: true
    Why:

    The key is write-only but lacks format: password, so tooling cannot distinguish it from any other write-only string field.

    1. Identify all properties that carry a secret value per IPA-111.

    2. Confirm each such property sets format: password in its schema.

    3. Report secret-carrying properties that omit format: password.

    Depends on
  2. Must not use format: password on a redacted sibling property whose value is a masked display (****, last-4 digits, etc.). The redacted value is not itself a secret; marking it as such misleads consumers and tooling.

    components:
    schemas:
    ApiKey:
    type: object
    properties:
    key:
    type: string
    format: password
    writeOnly: true
    keyRedacted:
    type: string
    description: Last four characters of the API key.
    readOnly: true
    Why:

    Only the raw key carries format: password. The redacted sibling keyRedacted carries a masked display, not a secret, so it omits the format.

    components:
    schemas:
    ApiKey:
    type: object
    properties:
    key:
    type: string
    format: password
    writeOnly: true
    keyRedacted:
    type: string
    format: password
    description: Last four characters of the API key.
    readOnly: true
    Why:

    keyRedacted is a masked display whose value is not a secret — it repeats a few characters the consumer already provided. Marking it with format: password misleads tooling into treating the redacted value as a secret.

    1. Identify redacted sibling properties — read-only fields that show a masked or truncated display of a sensitive field.

    2. Confirm none of these sibling properties carries format: password.

    3. Report redacted siblings that are incorrectly marked with format: password.

    Depends on

Examples

  1. API producers must provide a well-defined schema or example(s) for objects, request and response bodies, and parameters. Tools can leverage schemas and field examples to generate request and response examples.

    paths:
    /orders:
    post:
    summary: Create One Order
    requestBody:
    content:
    application/json:
    schema:
    $ref: "#/components/schemas/Order"
    responses:
    "201":
    description: Order created.
    content:
    application/json:
    schema:
    $ref: "#/components/schemas/Order"
    Why:

    Both the request and response bodies reference a defined schema, so tooling can generate accurate examples and consumers know the exact shape.

    paths:
    /orders:
    post:
    summary: Create One Order
    requestBody:
    content:
    application/json: {}
    responses:
    "201":
    description: Order created.
    content:
    application/json: {}
    Why:

    Neither body declares a schema or example, so the expected format is undefined and no tooling can describe or validate it.

  2. For APIs where fields can be mutually exclusive, API producers should provide correct examples to consumers on how to use the API.

    requestBody:
    content:
    application/json:
    schema:
    oneOf:
    - $ref: "#/components/schemas/PriceByAmount"
    - $ref: "#/components/schemas/PriceByPercentage"
    examples:
    byAmount:
    value: { amount: 500 }
    byPercentage:
    value: { percentage: 10 }
    Why:

    Each mutually exclusive variant has its own example, so a consumer sees a valid payload for each branch instead of guessing which fields combine.

    requestBody:
    content:
    application/json:
    schema:
    oneOf:
    - $ref: "#/components/schemas/PriceByAmount"
    - $ref: "#/components/schemas/PriceByPercentage"
    example:
    amount: 500
    percentage: 10
    Why:

    A single example sets both mutually exclusive fields at once, modeling an invalid payload and misleading consumers about how the variants are used.

    1. Find request and response bodies whose schema uses oneOf or otherwise marks fields as mutually exclusive.

    2. For each, check that examples demonstrate a valid combination for every branch and never set mutually exclusive fields together.

    3. Report bodies that lack per-variant examples or whose example violates the exclusivity constraint.

  3. For APIs that respond with plain text, for example CSV, API producers must provide an example, since some tools are not able to generate examples for such responses.

    responses:
    "200":
    description: Export of all invoices as CSV.
    content:
    text/csv:
    schema:
    type: string
    example: |
    id,total,status
    inv_1,500,PAID
    inv_2,750,OPEN
    Why:

    The plain-text response carries an explicit example, so tooling that cannot synthesize one still shows consumers the expected output.

    responses:
    "200":
    description: Export of all invoices as CSV.
    content:
    text/csv:
    schema:
    type: string
    Why:

    A bare type: string gives tooling nothing to render for a CSV body, leaving consumers without a sample of the format.

See schema example.

Default values

  1. API producers must document default values.

    properties:
    pageSize:
    type: integer
    description: Number of items returned per page.
    default: 100
    Why:

    The field declares its default with default, so a consumer who omits it knows the value that applies.

    properties:
    pageSize:
    type: integer
    description: Number of items returned per page. Defaults to 100 if omitted.
    Why:

    The default is buried in prose rather than declared with default, so tooling and generated clients cannot surface or validate it.

    1. Identify properties and parameters whose description or behavior implies a value that applies when the field is omitted.

    2. Confirm each such field declares that value with the default keyword rather than only mentioning it in prose.

    3. Report fields that have an implicit default but no default keyword.

See Default Values.

Validation Keywords

  1. API producers must detail the required or optional nature of the field and any conditions in both responses and requests.

    components:
    schemas:
    Order:
    type: object
    required: [customerId, total]
    properties:
    customerId:
    type: string
    total:
    type: integer
    note:
    type: string
    Why:

    The required list states which fields must be present, so a consumer knows exactly what each request and response guarantees.

    components:
    schemas:
    Order:
    type: object
    properties:
    customerId:
    type: string
    total:
    type: integer
    note:
    type: string
    Why:

    With no required list a consumer cannot tell which fields are mandatory, leaving the contract ambiguous in both directions.

    1. For each request and response schema, list its properties.

    2. Confirm the schema marks mandatory fields with required and that conditional requirements are documented in the description or schema composition.

    3. Report schemas where the required or optional status of a field cannot be determined from the spec.

  2. For string values API producers may document minLength, maxLength, and patterns, for example /^[a-zA-Z0-9][a-zA-Z0-9-]*$/.

  3. API producers should avoid overly specific patterns, since changes to a pattern can be considered a breaking change.

    properties:
    slug:
    type: string
    pattern: "^[a-zA-Z0-9][a-zA-Z0-9-]*$"
    Why:

    A broad shape constraint validates input without locking the API into details that may need to loosen later.

    properties:
    slug:
    type: string
    pattern: "^(prod|stg|dev)-[a-z]{3}-[0-9]{4}$"
    Why:

    A pattern that encodes exact prefixes and lengths must change whenever those details evolve, and tightening or loosening it is a breaking change.

    1. Collect every pattern constraint in the spec.
    2. Flag patterns that encode narrow business specifics — fixed prefixes, exact lengths, enumerated segments — rather than a general shape.

    3. Report each overly specific pattern, since later edits to it would break existing clients.

  4. For numeric values API producers may document minimum, exclusive minimum, maximum, and exclusive maximum.

  5. For array fields API producers may document minItems and maxItems.

  6. API producers must not combine unrelated validation keywords.

    properties:
    name:
    type: string
    minLength: 1
    maxLength: 64
    Why:

    Every keyword applies to the declared string type, so the constraints are coherent and enforceable.

    properties:
    name:
    type: string
    minLength: 1
    minimum: 0
    minItems: 1
    Why:

    minimum and minItems apply to numbers and arrays, not strings, so mixing them onto a string field is meaningless and confuses both readers and validators.

    1. For each schema, read its declared type and the validation keywords it sets.

    2. Check that every keyword applies to that type: string keywords on strings, numeric keywords on numbers, array keywords on arrays.

    3. Report any schema that carries validation keywords belonging to an unrelated type.

See validations for a full list of available validations.

Operation Summary

Operation summaries are titles describing an API operation.

  1. Operation summaries must be concise.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    Why:

    A short title names the operation at a glance, which is all a summary is for.

    paths:
    /orders/{orderId}:
    get:
    summary: >-
    Return One Order by Its Identifier Including All Line Items and the
    Current Shipping Status for the Authenticated Caller
    Why:

    A summary stuffed with behavioral detail stops being a title; that detail belongs in the description.

    1. For each operation, read its summary.
    2. Confirm the summary is a short title — roughly a noun phrase, not a sentence of behavioral detail.

    3. Report summaries that carry usage detail or nuance that belongs in the description.

  2. Operation summaries should describe what an operation does, but should not describe in-depth information about how to use it or nuances in behavior. For additional details about the behavior of the operations, refer to Descriptions.

    paths:
    /projects/{projectId}/members:
    post:
    summary: Add One Member to One Project
    description: >-
    Adds a member to the project. The caller must have the project owner
    role. Members added this way inherit the default project role.
    Why:

    The summary states what the operation does; the how-to-use detail lives in the description where consumers expect it.

    paths:
    /projects/{projectId}/members:
    post:
    summary: >-
    Add One Member to One Project, Which Requires the Owner Role and Applies
    the Default Project Role to the New Member
    Why:

    The summary absorbs behavioral nuance that belongs in the description, so it no longer reads as a title.

    1. For each operation, read its summary and description.

    2. Confirm the summary states what the operation does and that usage detail or behavioral nuance lives in the description instead.

    3. Report summaries that carry how-to-use or edge-case detail.

Formatting

  1. Summaries must use Title Case.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    Why:

    Title Case matches the convention used for every operation title in the reference.

    paths:
    /orders/{orderId}:
    get:
    summary: Return one order
    Why:

    Sentence case breaks the consistent title styling readers rely on to scan the operation list.

  2. Summaries must not end with a period.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    Why:

    A title is not a sentence, so it carries no terminating punctuation.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order.
    Why:

    A trailing period treats the title as a sentence and diverges from the rest of the operation list.

  3. Summaries must not use CommonMark.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    Why:

    A plain-text title renders identically everywhere a summary appears.

    paths:
    /orders/{orderId}:
    get:
    summary: Return One `Order`
    Why:

    Markdown in a title surfaces as literal backticks or markup in tools that do not render CommonMark in summary fields.

Language

  1. API producers must use "One" when referring to a single item instead of "a" or "specified".

    paths:
    /orders/{orderId}:
    get:
    summary: Return One Order
    Why:

    "One" states the cardinality plainly and matches the wording used for every single-item operation.

    paths:
    /orders/{orderId}:
    get:
    summary: Return a Specified Order
    Why:

    "a" and "Specified" are vaguer and inconsistent ways to say the same thing that "One" expresses directly.

  2. API producers must use "Return" instead of "Get" or "List".

    paths:
    /orders:
    get:
    summary: Return All Orders
    Why:

    "Return" is the single read verb used across the API, so consumers scan for one word rather than several synonyms.

    paths:
    /orders:
    get:
    summary: List Orders
    Why:

    "List" and "Get" are interchangeable synonyms for the same read action and fragment the vocabulary consumers must learn.

  3. API producers must not use "Return All" unless the API can really return all items in a collection. Collections may contain an unbounded number of entries and must be paginated (see Pagination); if the total number of entries can exceed the page size and prevent the client from accessing the full set, do not use "All".

    paths:
    /orders:
    get:
    summary: Return All Orders
    description:
    Returns every order. The result set is bounded and not paginated.
    Why:

    "All" is accurate only because the operation genuinely returns the entire bounded collection in one response.

    paths:
    /orders:
    get:
    summary: Return All Orders
    parameters:
    - name: pageNum
    in: query
    schema:
    type: integer
    - name: itemsPerPage
    in: query
    schema:
    type: integer
    Why:

    The operation is paginated, so a single call returns one page rather than every order; "All" overstates what the consumer receives.

    1. Find get operations whose summary starts with "Return All".

    2. For each, determine whether the operation is paginated or otherwise capped below the full collection size — look for page or limit parameters and the response envelope.

    3. Report any "Return All" summary on an operation that cannot return the entire collection in one response.

  4. API producers must use "Update" instead of "Modify" or "Change".

    paths:
    /orders/{orderId}:
    patch:
    summary: Update One Order
    Why:

    "Update" is the single mutation verb used across the API for editing an existing resource.

    paths:
    /orders/{orderId}:
    patch:
    summary: Modify One Order
    Why:

    "Modify" and "Change" are synonyms for "Update" that add vocabulary without adding meaning.

  5. API producers should use "Delete" when the operation is destroying a resource, and should use "Remove" when the resource itself is not being destroyed.

    paths:
    /orders/{orderId}:
    delete:
    summary: Delete One Order
    /projects/{projectId}/members/{userId}:
    delete:
    summary: Remove One Member from One Project
    Why:

    "Delete" marks the destruction of the order, while "Remove" marks disassociating a member who continues to exist, so the verb signals the effect.

    paths:
    /projects/{projectId}/members/{userId}:
    delete:
    summary: Delete One Member from One Project
    Why:

    "Delete" implies the member is destroyed, but the operation only removes the member from the project, so "Remove" is the accurate verb.

  6. API producers should use "Create" when the operation is creating a resource, and should use "Add" when the resource itself is not being created.

    paths:
    /orders:
    post:
    summary: Create One Order
    /projects/{projectId}/members:
    post:
    summary: Add One Member to One Project
    Why:

    "Create" marks bringing a new order into existence, while "Add" marks associating an existing user with a project, so the verb signals the effect.

    paths:
    /projects/{projectId}/members:
    post:
    summary: Create One Member in One Project
    Why:

    "Create" implies a new member resource is brought into being, but the operation only associates an existing user, so "Add" is the accurate verb.

  7. API producers must use "Reset" when the operation is restoring a resource to its default state.

    paths:
    /projects/{projectId}/settings:reset:
    post:
    summary: Reset Settings for One Project
    Why:

    "Reset" names the effect precisely: the settings return to their default state rather than being edited or removed.

    paths:
    /projects/{projectId}/settings:reset:
    post:
    summary: Update Settings for One Project to Default
    Why:

    "Update" describes an arbitrary edit, hiding that the operation restores the default state, which "Reset" conveys directly.

    1. Find operations whose behavior restores a resource to its default state.

    2. Confirm each such summary uses "Reset" rather than "Update" or another verb.

    3. Report restore-to-default operations whose summary uses a different verb.

  8. API producers must use only one main action verb, for example "Create", "Update", "Delete", "Add", or "Remove".

    paths:
    /orders/{orderId}:
    patch:
    summary: Update One Order
    Why:

    A single action verb states exactly one effect, so the summary is unambiguous.

    paths:
    /orders/{orderId}:
    patch:
    summary: Update and Reset One Order
    Why:

    Two action verbs describe two effects in one title, leaving a consumer unsure what the operation actually does.

    1. For each operation, read its summary and identify the action verbs it contains.

    2. Confirm exactly one main action verb is present.

    3. Report summaries that chain more than one action verb.

  9. API producers must not use abbreviations and technical formatting in summaries — for example "Line Items" instead of "lineItems", "Organization Configuration" instead of "Org Config", and "Feature Compatibility Version" instead of "FCV".

    paths:
    /orders/{orderId}/line-items:
    get:
    summary: Return All Line Items for One Order
    Why:

    Spelled-out words in normal title casing read as prose to any consumer, not as code identifiers.

    paths:
    /orders/{orderId}/line-items:
    get:
    summary: Return All lineItems for One Order
    Why:

    A camelCase identifier and a code-style abbreviation leak technical formatting into a human-facing title.

    1. For each operation, read its summary.
    2. Flag camelCase or snake_case identifiers, code-style tokens, and unexpanded abbreviations.

    3. Report summaries that use technical formatting where spelled-out words belong.

  10. API producers must use "by" when referring to how something should be queried — for example "Return One Event by ID" instead of "Return One Event Using Its ID".

    paths:
    /events/{eventId}:
    get:
    summary: Return One Event by ID
    Why:

    "by" is the consistent connector for query criteria across the API.

    paths:
    /events/{eventId}:
    get:
    summary: Return One Event Using Its ID
    Why:

    "Using Its" is a wordier connector that says the same thing as "by" and breaks the consistent phrasing.

    1. Find summaries that name the criterion used to select a resource.

    2. Confirm the connector is "by" rather than a wordier phrase such as "using its" or "with".

    3. Report summaries that express query criteria with a connector other than "by".

  11. API producers must use "in" for actions operating within the parent (retrieving, updating, creating) and "from" for removing or disassociating — for example "Update One Member in One Project" and "Remove One Member from One Project".

    paths:
    /projects/{projectId}/members/{userId}:
    patch:
    summary: Update One Member in One Project
    delete:
    summary: Remove One Member from One Project
    Why:

    "in" marks an action within the parent and "from" marks disassociation, so the preposition signals the relationship the operation has with the parent.

    paths:
    /projects/{projectId}/members/{userId}:
    delete:
    summary: Remove One Member in One Project
    Why:

    "in" describes acting within the project, but removal disassociates the member from it, so "from" is the accurate preposition.

    1. Find summaries that relate a sub-resource to a parent resource.

    2. For each, check the preposition: "in" for retrieving, updating, or creating within the parent; "from" for removing or disassociating.

    3. Report summaries whose preposition does not match the action.

  12. API producers should avoid unnecessary filler words, for example "possible", "available", or "current".

    paths:
    /orders:
    get:
    summary: Return All Orders
    Why:

    Every word in the title carries meaning, so nothing distracts from what the operation does.

    paths:
    /orders:
    get:
    summary: Return All Currently Available Orders
    Why:

    "Currently" and "Available" add no information beyond "Return All Orders" and pad the title.

    1. For each operation, read its summary.
    2. Flag filler words such as "possible", "available", or "current" that do not change the meaning of the title.

    3. Report summaries that carry such filler.

Further reading