Documenting a URL does not fully describe what clients can do with it. A bookstore might expose /books/bk_1042 both for readers to retrieve a published book and for authorized staff to remove its public listing. The URL is the same, but the methods, permissions, and successful outcomes differ. A description that lists only the URL leaves most of that contract unstated.
OpenAPI represents this distinction through paths and operations.
This chapter explains how to define them, share settings where appropriate, avoid ambiguous path templates, and give each operation a clear identity. The examples use OpenAPI 3.1.2 and a fictional bookstore API over HTTPS.
The root paths object maps URL paths to Path Item Objects. Each Path Item groups the operations available at one path. An Operation Object describes one HTTP method on that path.
For the bookstore, GET /books/{bookId} retrieves a published book, while DELETE /books/{bookId} removes its public listing. Both belong under the same /books/{bookId} entry. The braces identify a variable part of the path.
The diagram shows how a shared target leads to different contracts. Authentication and response handling belong to the selected operation, not merely to the URL.
Defining one operation does not define its siblings. A get entry does not automatically document head, and it does not imply that callers may use delete.
In OpenAPI 3.1.2, the supported method fields on a Path Item are get, put, post, delete, options, head, patch, and trace. These YAML keys use lowercase even though HTTP request examples use method tokens such as GET. Define the methods your service exposes; do not add every method as a placeholder.
A path and method pair has one Operation Object. Query values, request media types, and different response outcomes belong inside that operation's description. They do not create additional get or post entries with the same key.
A path key starts with /. Append it to the applicable server URL to form the endpoint address. With the server URL https://api.bookstore.example, the path /books/{bookId} and the value bk_1042 identify https://api.bookstore.example/books/bk_1042.
Keep the hostname in servers. Keep query parameters out of the path key: describe a request such as /books?author=Eve under the /books path and define author as a query parameter. A URL fragment is not a server request target and has no place in a path key either.
OpenAPI uses brace-delimited names such as {bookId}. Router notation such as :bookId or a framework-specific regular expression is not equivalent OpenAPI template syntax.
Every placeholder in an operation's path needs a corresponding path parameter. Its name must match exactly, its location must be path, and it must declare required: true. The definition can sit on the Path Item or on each operation that needs it.
For example, this Path Item fragment declares the shared variable:
The parameter supplies information about the placeholder; it does not create another URL segment. Using name: id for a {bookId} placeholder would leave the template without its matching definition.
Path parameters are not optional. If a service supports both a collection and an individual item, describe /books and /books/{bookId} separately instead of trying to make the last segment optional.
Treat values as data, not as extra path syntax. Raw /, ?, and # characters have structural meaning in URLs. Do not assume a template provides a portable way to capture arbitrary nested paths. For this API, identifiers such as bk_1042 avoid that issue.
Assume anyone can retrieve a published book. Removing a listing requires a valid staff bearer token and catalog-management permission. Removal affects the public catalog; it does not erase the bookstore's historical order records.
The API checks staff authentication and permission before looking up the book for deletion. It returns bodyless 401, 403, or 404 responses for the corresponding failures. A successful deletion returns 204. Deleting the same identifier again returns 404, because no published listing remains. The different status on a repeated DELETE does not undermine idempotency: the intended effect remains an absent listing. These are explicit design choices for this API.
The following document describes both operations. The Book schema stays inline, and error responses have no bodies, so the example can concentrate on operation boundaries.
Both operations use the Path Item's bookId parameter, but they have independent response maps. The public get inherits the empty root security requirement. The delete operation declares its own bearer requirement.
staffBearer identifies how clients supply credentials. It does not express or enforce the catalog-management permission itself. The operation description explains that additional business rule, and the service must implement it.
The example has no request body or custom identifier-format constraint, so it does not invent a body-validation error. Adding inputs with validation rules would require describing the corresponding failure behavior on the affected operation.
Here is a public retrieval before the staff member removes the listing:
The response body below is compact UTF-8 JSON with no trailing newline:
A staff member with the required permission can then remove the listing. The token in this example is a nonfunctional placeholder.
The successful response contains no body:
A request without credentials uses the same target:
The authentication check produces this response before any book lookup:
A later public GET for the removed listing returns the documented 404. These outcomes belong to the individual operations, even though all requests use the same path.
Sharing a path does not make every field shareable. The Path Item supports common parameters, server settings, a summary, and a description. Fields such as requestBody, responses, security, tags, operationId, and deprecated belong on individual operations.
The distinction is useful in the bookstore example. The identifier means the same thing for retrieval and removal, so the Path Item defines it once. The permission rule applies only to removal, so it stays inside delete.
Parameter inheritance has a specific rule: a parameter's identity is the combination of its name and location. An operation can add parameters or override a Path Item parameter with the same identity. It cannot remove a shared parameter by omission or by declaring parameters: [].
Suppose retrieval later accepts an optional include query parameter for additional public details. Place that parameter inside get unless deletion also supports it. Moving it to the Path Item merely to keep the file shorter would incorrectly make it apply to both operations.
These settings have different scope behavior:
In particular, an empty operation parameter list and an empty operation security list do different things. An empty parameter list keeps shared parameters; an empty security list removes the root security requirement. Read each field's rules instead of assuming every nested list behaves the same way.
Path templates should make request targets easy to distinguish. OpenAPI specifies that a concrete path matches before its templated counterpart. If the API defines both /books/search and /books/{bookId}, the request path /books/search selects the concrete entry.
The diagram illustrates that precedence for this pair of paths, assuming the selected path documents GET:
The literal segment search now has a reserved role in that URL space. If book identifiers could equal search, a client could not use that path to retrieve such a book through the template. A naming decision can therefore affect which identifiers remain addressable.
Some path pairs are invalid rather than merely confusing. Defining /books/{bookId} and /books/{slug} as separate entries is intentionally flawed: their hierarchy is identical, and changing the placeholder name does not distinguish them. Assigning different methods or parameter schemas does not fix the duplicate template shape.
Use one consistent template when both operations address the same resource. If the API really offers two lookup forms, give them distinct targets, such as /books/{bookId} and /books/by-slug/{slug}, and define each placeholder for its operation. Those URL choices are conventions for this example, not required OpenAPI names.
Other patterns can overlap without being identical. For example, /books/{bookId} and /{collection}/search can both match /books/search. OpenAPI leaves ambiguous matching to tooling, so avoid relying on which branch a particular tool happens to choose. Replacing the broad second template with a concrete /books/search makes the intended distinction explicit.
The description does not configure a handwritten server router automatically. Check the real service's route precedence against the documented paths. Rearranging YAML entries is not a reliable way to repair an ambiguous contract or a differently configured router.
An operation has both a wire-level identity and an optional operationId. The path and method tell a client how to call it. The operationId gives tools a name by which to identify it.
If you supply one, an operationId must be unique across all operations in the API, not merely within a tag or Path Item. getBook and deleteBookListing communicate different intentions. Reusing getBook for an unrelated inventory lookup would create a collision even if the URLs differed.
Use a consistent programming-style naming convention and keep names stable. Many generators use operation IDs when choosing client method names. Renaming an ID can therefore change generated client interfaces even if the HTTP request stays identical; the exact result depends on the generator.
Although operation IDs are case-sensitive, avoid names that differ only in casing, such as getBook and GetBook. Toolchains may normalize names for a target language, and the distinction is unnecessarily hard for people to review. Prefer names that explain the operation rather than its current controller class or database table.
The surrounding metadata serves different readers. A summary gives a short action label. A description explains behavior, permissions, side effects, and meaningful edge cases. tags organizes operations into useful groups. Neither a tag nor an operation ID changes routing.
For removal, “Remove a published book listing” is a useful summary. The description then explains what remains in historical records and what happens on repeated calls. Repeating the summary in a longer sentence would add less value than explaining those decisions.
An operation can also declare deprecated: true. That marker advises consumers to move away from it; it does not disable the route, redirect requests, or schedule removal. Apply it to the specific operation you plan to retire and explain the replacement behavior. There is no Path Item deprecated field in OpenAPI 3.1.2 for retiring every method at once.
Review paths and operations together. A well-written operation can still be difficult to use if its path conflicts with another template or its shared parameters describe inputs it does not support.
For each path, confirm that placeholders match declared required parameters, method keys use the supported spelling, and there is only one entry per path and method. Check template shapes as well as literal YAML keys: a parser will not recognize that {bookId} and {slug} represent the same structural position.
Then inspect the operation's identity, effective security requirements, and outcomes. For the bookstore, reviewers should be able to establish that GET is public, DELETE requires staff authorization, and the two operations have different successful responses without guessing from their names.
OpenAPI 3.1.2 does not mark responses as a required Operation Object field. Nevertheless, documenting success and relevant failures is a practical requirement for a usable contract. If a Responses Object is present, it must contain at least one response entry, and each inline Response Object requires a description. A permissive structural minimum is not a good target for consumer documentation.
Finally, verify representative requests against the service, especially a literal path that could collide with a template and an operation whose permissions differ from its siblings. Document validation catches structural problems; those runtime checks reveal whether the service implements the operation that the document describes.
Paths identify request targets, and operations define what each HTTP method does at those targets. Use matching required parameters for path placeholders, keep shared settings limited to what applies to every operation, and describe each operation's permissions and outcomes explicitly.
Avoid duplicate or overlapping template shapes, choose unique and stable operation IDs, and use descriptions for behavior that names alone cannot explain. A clear definition should let readers determine which operation a request selects and what contract applies when they call it.