IPA-104: Get
In REST APIs, it is customary to make a GET request to a resource's URI (for
example, /projects/{projectId}/tasks/{taskId}) to retrieve that resource.
Guidance
APIs must provide a Get method for resources.
paths:
/projects/{projectId}:
get:
operationId: getProject
responses:
"200":
description: OKWhy:The single-resource path exposes a
GET, so the resource can be read back.paths:
/projects/{projectId}:
put:
operationId: updateProject
delete:
operationId: deleteProjectWhy:The resource can be updated and deleted but never retrieved, so callers have no way to read its current state.
Enumerate every entry under
pathsand 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
getoperation.Report any resource whose single-resource or singleton path has no
getoperation.
A Get method must return data from a single resource, not a collection or a paginated list.
paths:
/projects/{projectId}:
get:
operationId: getProject
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/ProjectResponse"Why:The response is a single object describing one project.
paths:
/projects/{projectId}:
get:
operationId: getProject
responses:
"200":
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/ProjectResponse"Why:An array response describes a collection, which belongs on the List method, not the Get method for one resource.
Collect every
getoperation defined on a single-resource path or a singleton.For each
2xxresponse, follow the content schema (resolving any$ref) and inspect itstype.Confirm the schema is a single object and not an
arrayor a paginated envelope (a wrapper carryingresults,totalCount, or similar list metadata).Report any Get response whose schema is an array or a paginated result.
The HTTP verb must be
GET.paths:
/orders/{orderId}:
get:
operationId: getOrderWhy:Retrieving a resource uses the
GETverb, the safe, read-only HTTP method.paths:
/orders/{orderId}:
post:
operationId: getOrderWhy:POSTis 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
getand notpost,put,patch, ordelete.Report any single-resource read modeled under a verb other than
get.
The Get method must not cause side effects.
paths:
/orders/{orderId}:
get:
operationId: getOrder
description: Returns the order. Does not modify any stored state.Why:A Get only reads, so repeated calls return the same data and leave server state unchanged.
paths:
/orders/{orderId}:
get:
operationId: getOrder
description:
Returns the order and marks it as viewed, decrementing its TTL.Why:Mutating state on read makes the call unsafe, so caching, retries, and prefetching can silently change data.
Collect every
getoperation 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.
The request must not include a body.
paths:
/orders/{orderId}:
get:
operationId: getOrder
parameters:
- name: orderId
in: path
required: true
schema:
type: stringWhy:The resource is identified entirely by the path, so no request body is defined.
paths:
/orders/{orderId}:
get:
operationId: getOrder
requestBody:
content:
application/json:
schema:
type: objectWhy:A
GETbody is ignored by many clients, proxies, and caches, so any input carried there cannot be relied on.A Get method should return a
Responsesuffixed object.paths:
/orders/{orderId}:
get:
operationId: getOrder
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/OrderResponse"Why:The response references a named, reusable
OrderResponseschema, which keeps output models distinct from input models.paths:
/orders/{orderId}:
get:
operationId: getOrder
responses:
"200":
content:
application/json:
schema:
type: object
properties:
id:
type: stringWhy:An inline, unnamed schema cannot be referenced or named consistently, so the output model is not reusable across operations.
A
Responseobject must not include fields available only on creation or update — in OpenAPI, fields markedwriteOnly: true.components:
schemas:
OrderResponse:
type: object
properties:
id:
type: string
total:
type: numberWhy:Every property is readable, so the response carries only fields a reader can see.
components:
schemas:
OrderResponse:
type: object
properties:
id:
type: string
cardNumber:
type: string
writeOnly: trueWhy:A
writeOnlyfield 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.
paths:
/orders/{orderId}:
get:
operationId: getOrder
responses:
"200":
description: OKWhy:A successful read returns
200 OK, the standard status for a retrieved resource.paths:
/orders/{orderId}:
get:
operationId: getOrder
responses:
"201":
description: CreatedWhy:201 Createdsignals that a resource was created, which never happens on a read.The response may include a HATEOAS
linksfield.
Example
GET /projects/${projectId}/tasks/${taskId}
Naming
Operation ID must be unique.
paths:
/projects/{projectId}:
get:
operationId: getProject
/orders/{orderId}:
get:
operationId: getOrderWhy:Each operation has a distinct
operationId, so generated method names do not collide.paths:
/projects/{projectId}:
get:
operationId: get
/orders/{orderId}:
get:
operationId: getWhy:Two operations share the
operationIdget, so one overwrites the other in generated clients.Collect the
operationIdof every operation across all paths and methods.Compare the values and find any
operationIdthat appears more than once.Report each duplicated
operationId, naming the operations that share it.
Operation ID must be in
camelCase.paths:
/projects/{projectId}:
get:
operationId: getProjectWhy:getProjectiscamelCase, matching the casing every generated client expects.paths:
/projects/{projectId}:
get:
operationId: get_projectWhy:get_projectis snake_case, so generated method names are inconsistent with the rest of the API.Operation ID must start with the verb "get".
paths:
/projects/{projectId}:
get:
operationId: getProjectWhy:The
operationIdbegins withget, matching the read semantics of the method.paths:
/projects/{projectId}:
get:
operationId: fetchProjectWhy:fetchProjectuses 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.
paths:
/projects/{projectId}/tasks/{taskId}:
get:
operationId: getProjectTaskWhy:ProjectTaskis the collection identifiersprojectsandtasksin singular form, so the name mirrors the resource path.paths:
/projects/{projectId}/tasks/{taskId}:
get:
operationId: getProjectsTasksWhy: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, the last noun may be the plural form of the collection identifier.
Examples:
| Resource Identifier | Operation ID |
|---|---|
/projects/${projectId}/tasks/${taskId} | getProjectTask |
(Singleton) /projects/${projectId}/settings | getProjectSettings |
Error Handling
See IPA-114: Errors for guidance on error handling and documentation, in particular Authentication, Authorization and Not Found.