diff --git a/ipa/general/0104.mdx b/ipa/general/0104.mdx
index 3ebd39b..b2c8c31 100644
--- a/ipa/general/0104.mdx
+++ b/ipa/general/0104.mdx
@@ -6,49 +6,699 @@ state: adopt
# IPA-104: Get
In REST APIs, it is customary to make a `GET` request to a resource's URI (for
-example, `/groups/{groupId}/clusters/{clusterName}`) to retrieve that resource.
+example, `/projects/{projectId}/tasks/{taskId}`) to retrieve that resource.
## Guidance
-- APIs **must** provide a Get method for resources
-- The purpose of the Get method is to return data from a single resource
-- The HTTP verb **must** be
- [`GET`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET)
-- The method **must not** [cause side effects](0103.mdx)
-- The request **must not** include a body
-- API producers **should** implement as a `Response` suffixed object
- - A `Response` object **must not** include fields available only on creation
- or update
- - In OpenAPI, this means that the `Response` object **must not** include
- fields with `writeOnly: true`
-- The response status code **must** be
- [200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200)
-- The response **may** include a
- [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS) `links` field
+
+
+
+
+APIs **must** provide a Get method for resources.
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: getProject
+ responses:
+ "200":
+ description: OK
+```
+
+
+ The single-resource path exposes a `GET`, so the resource can be read back.
+
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ put:
+ operationId: updateProject
+ delete:
+ operationId: deleteProject
+```
+
+
+ The resource can be updated and deleted but never retrieved, so callers have
+ no way to read its current state.
+
+
+
+
+
+
+ Enumerate every entry under `paths` and group the paths by the resource they
+ address.
+
+
+ For each resource that has a single-resource path (a path ending in a
+ resource identifier) or is a singleton, confirm that path defines a `get`
+ operation.
+
+
+ Report any resource whose single-resource or singleton path has no `get`
+ operation.
+
+
+
+
+
+
+
+
+
+A Get method **must** return data from a single resource, not a collection or a
+paginated list.
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: getProject
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ProjectResponse"
+```
+
+
+ The response is a single object describing one project.
+
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: getProject
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: "#/components/schemas/ProjectResponse"
+```
+
+
+ An array response describes a collection, which belongs on the List method,
+ not the Get method for one resource.
+
+
+
+
+
+
+ Collect every `get` operation defined on a single-resource path or a
+ singleton.
+
+
+ For each `2xx` response, follow the content schema (resolving any `$ref`)
+ and inspect its `type`.
+
+
+ Confirm the schema is a single object and not an `array` or a paginated
+ envelope (a wrapper carrying `results`, `totalCount`, or similar list
+ metadata).
+
+
+ Report any Get response whose schema is an array or a paginated result.
+
+
+
+
+
+
+
+
+
+The HTTP verb **must** be
+[`GET`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET).
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+```
+
+
+ Retrieving a resource uses the `GET` verb, the safe, read-only HTTP method.
+
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ post:
+ operationId: getOrder
+```
+
+
+ `POST` is not safe and not idempotent, so it cannot stand in for a read of a
+ single resource.
+
+
+
+
+
+
+ For each operation whose intent is to retrieve a single resource, read the
+ HTTP method it is defined under in the path item.
+
+
+ Confirm the method is `get` and not `post`, `put`, `patch`, or `delete`.
+
+
+ Report any single-resource read modeled under a verb other than `get`.
+
+
+
+
+
+
+
+
+
+The Get method **must not** [cause side effects](0103.mdx).
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ description: Returns the order. Does not modify any stored state.
+```
+
+
+ A Get only reads, so repeated calls return the same data and leave server
+ state unchanged.
+
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ description:
+ Returns the order and marks it as viewed, decrementing its TTL.
+```
+
+
+ Mutating state on read makes the call unsafe, so caching, retries, and
+ prefetching can silently change data.
+
+
+
+
+
+
+ Collect every `get` operation on a single resource or singleton.
+
+
+ Read the operation description and, where available, the handler source it
+ maps to, since whether a read mutates state cannot be told from the contract
+ alone.
+
+
+ Determine whether the operation writes to storage, enqueues work, sends
+ notifications, or otherwise changes observable state.
+
+
+ Report any Get whose implementation produces a side effect, per
+ [IPA-103](0103.mdx).
+
+
+
+
+
+
+
+
+
+The request **must not** include a body.
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ parameters:
+ - name: orderId
+ in: path
+ required: true
+ schema:
+ type: string
+```
+
+
+ The resource is identified entirely by the path, so no request body is
+ defined.
+
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+```
+
+
+ A `GET` body is ignored by many clients, proxies, and caches, so any input
+ carried there cannot be relied on.
+
+
+
+
+
+
+
+
+
+
+A Get method **should** return a `Response` suffixed object.
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/OrderResponse"
+```
+
+
+ The response references a named, reusable `OrderResponse` schema, which keeps
+ output models distinct from input models.
+
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ id:
+ type: string
+```
+
+
+ An inline, unnamed schema cannot be referenced or named consistently, so the
+ output model is not reusable across operations.
+
+
+
+
+
+
+
+
+
+
+A `Response` object **must not** include fields available only on creation or
+update — in OpenAPI, fields marked `writeOnly: true`.
+
+
+
+
+
+```yaml
+components:
+ schemas:
+ OrderResponse:
+ type: object
+ properties:
+ id:
+ type: string
+ total:
+ type: number
+```
+
+
+ Every property is readable, so the response carries only fields a reader can
+ see.
+
+
+
+
+
+
+```yaml
+components:
+ schemas:
+ OrderResponse:
+ type: object
+ properties:
+ id:
+ type: string
+ cardNumber:
+ type: string
+ writeOnly: true
+```
+
+
+ A `writeOnly` field is only meaningful on input, so its presence in a response
+ schema advertises a value that is never returned.
+
+
+
+
+
+
+
+
+
+
+The response status code **must** be
+[200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200).
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ responses:
+ "200":
+ description: OK
+```
+
+
+ A successful read returns `200 OK`, the standard status for a retrieved
+ resource.
+
+
+
+
+
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+ responses:
+ "201":
+ description: Created
+```
+
+
+ `201 Created` signals that a resource was created, which never happens on a
+ read.
+
+
+
+
+
+
+
+
+
+ The response **may** include a
+ [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS) `links` field.
+
+
+
Example
```http request
-GET /groups/${groupId}/clusters/${clusterName}
+GET /projects/${projectId}/tasks/${taskId}
```
### Naming
-- Operation ID **must** be unique
-- Operation ID **must** be in `camelCase`
-- Operation ID **must** start with the verb “get”
-- Operation ID **should** be followed by a noun or compound noun
- - The noun(s) in the Operation ID **should** be the collection identifiers
- from the resource identifier in singular form
- - If the resource is a [singleton](0113.mdx), the last noun **may** be the
- plural form of the collection identifier
+
+
+
+
+Operation ID **must** be unique.
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: getProject
+ /orders/{orderId}:
+ get:
+ operationId: getOrder
+```
+
+
+ Each operation has a distinct `operationId`, so generated method names do not
+ collide.
+
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: get
+ /orders/{orderId}:
+ get:
+ operationId: get
+```
+
+
+ Two operations share the `operationId` `get`, so one overwrites the other in
+ generated clients.
+
+
+
+
+
+
+ Collect the `operationId` of every operation across all paths and methods.
+
+
+ Compare the values and find any `operationId` that appears more than once.
+
+
+ Report each duplicated `operationId`, naming the operations that share it.
+
+
+
+
+
+
+
+
+
+Operation ID **must** be in `camelCase`.
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: getProject
+```
+
+
+ `getProject` is `camelCase`, matching the casing every generated client
+ expects.
+
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: get_project
+```
+
+
+ `get_project` is snake_case, so generated method names are inconsistent with
+ the rest of the API.
+
+
+
+
+
+
+
+
+
+
+Operation ID **must** start with the verb "get".
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: getProject
+```
+
+
+ The `operationId` begins with `get`, matching the read semantics of the
+ method.
+
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}:
+ get:
+ operationId: fetchProject
+```
+
+
+ `fetchProject` uses a different verb, so the name no longer signals a Get
+ method consistently across the API.
+
+
+
+
+
+
+
+
+
+
+Operation ID **should** be followed by a noun or compound noun, and that noun
+**should** be the collection identifiers from the resource identifier in
+singular form.
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}/tasks/{taskId}:
+ get:
+ operationId: getProjectTask
+```
+
+
+ `ProjectTask` is the collection identifiers `projects` and `tasks` in singular
+ form, so the name mirrors the resource path.
+
+
+
+
+
+
+```yaml
+paths:
+ /projects/{projectId}/tasks/{taskId}:
+ get:
+ operationId: getProjectsTasks
+```
+
+
+ The plural collection names do not match the singular-resource read, so the
+ name describes a collection rather than the single task being retrieved.
+
+
+
+
+
+
+
+
+
+ If the resource is a [singleton](0113.mdx), the last noun **may** be the
+ plural form of the collection identifier.
+
+
+
Examples:
-| Resource Identifier | Operation ID |
-| -------------------------------------------- | ------------------ |
-| `/groups/${groupId}/clusters/${clusterName}` | `getGroupCluster` |
-| (Singleton) `/groups/${groupId}/settings` | `getGroupSettings` |
+| Resource Identifier | Operation ID |
+| --------------------------------------------- | -------------------- |
+| `/projects/${projectId}/tasks/${taskId}` | `getProjectTask` |
+| (Singleton) `/projects/${projectId}/settings` | `getProjectSettings` |
### Error Handling