Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aep/general/0062/aep.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ Common uses for query parameters in APIs include:

* Filtering: `?status=active&type=premium`
* Pagination: `?page=2&limit=50`
* Sorting: `?sort=created_time&order=desc`
* Sorting: `?orderBy=createdTime`

Query parameter keys are typically **case-sensitive**, though this behavior can vary by server implementation. To avoid
ambiguity, assume parameter keys are case-sensitive unless explicitly documented otherwise. Also, maintain consistent
Expand Down
66 changes: 11 additions & 55 deletions aep/general/0065/aep.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# GET

In REST APIs, it is customary to make a `GET` request to a resource's URI (for example,
`/publishers/{publisher_id}/books/{book_id}`) in order to retrieve that resource. `GET` requests are used to read either
In REST APIs, it is customary to make a `GET` request to fetch data. `GET` requests are used to read either
a single resource or a collection of resources. As defined in [RFC 9110 Section 9.3.1], `GET` is the primary mechanism
for information retrieval in HTTP and should be [safe] and [idempotent].

Expand All @@ -14,7 +13,7 @@ collections.

**Use `GET` when:**

* Retrieving a specific resource by its ID (e.g., "Get user 123").
* Retrieving a specific resource by its ID (e.g., "Fetch user 123").
* Listing resources in a collection (e.g., "List all books").
* Searching or filtering data where the query parameters fit within the URL length limit.
* The operation is read-only and safe to cache.
Expand All @@ -28,9 +27,7 @@ collections.

### General requirements

* `GET` **must** be used to retrieve a representation of a resource.
* APIs **must** provide a `GET` method for resources unless there is a compelling reason not to do so. The purpose of
the `GET` method is to retrieve and return data about the resource.
* `GET` **must** be used to retrieve a representation of a resource or collection.
* `GET` requests **must not** have a request body payload.
* If a `GET` request contains a body, the body **must** be ignored, and **must not** cause an error.
* Be aware that some HTTP clients, proxies, and intermediaries may drop the request body or reject the request
Expand All @@ -39,36 +36,6 @@ collections.
see [GET with body](#get-with-body).
* `GET` requests **must** be [safe], meaning they **must not** modify server state or have side effects.
* `GET` requests **must** be [idempotent], meaning multiple identical requests **must** produce the same result.
* Some resources take longer to be retrieved than is reasonable for a regular API request. In this situation, the
API **should** use a [long-running operation].

### Individual Resources

`GET` requests for individual resources:

* **must** use the resource's canonical [URI path] (e.g., `/publishers/{publisher_id}/books/{book_id}`).
* **must** return a [200 OK] with the resource representation in the response body when the resource exists.
* **must** return a [404 Not Found] if the resource does not exist.
* If the resource previously existed and has since been deleted (e.g., soft-deleted), the server **may** instead
respond with [410 Gone].
* **may** support field masks or sparse fieldsets to allow clients to specify which fields they want returned, reducing
payload size and improving performance. See AEP-157 on partial responses for more details.

### Collection Resources

`GET` requests for collection resources:

* **must** use the collection's [URI path] (e.g., `/publishers/{publisher_id}/books`).
* **must** return a `[200 OK] when resources are successfully retrieved.
* The response body **must** be a wrapper object containing the list of resources, not a raw JSON array.
* These results **must** be [paginated].
* **must** return a [200 OK] with an empty array (inside the wrapper object) if the collection exists but contains no
resources.
* **should** return a [404 Not Found] if the parent resource does not exist (e.g., requesting
`/publishers/{invalid_id}/books` when the publisher doesn't exist).
* **should** implement sorting and [filtering] mechanisms to allow clients to sort and narrow results.
* The filters **must** follow the guidelines on [query parameters].
* **must** ensure a deterministic default sort order to guarantee stable [pagination].

### Caching

Expand All @@ -94,21 +61,16 @@ in the query string rather than the request body. This allows pagination links t
encodes page position and direction. The `cursor` may optionally include a hash of the applied filters to validate
consistency across paginated requests.

[RFC 9110 Section 9.3.1]: https://datatracker.ietf.org/doc/html/rfc9110#section-9.3.1

[safe]: /130#common-method-properties
## Further Reading

[idempotent]: /130#common-method-properties
- [Standard Action: Fetch](/fetch)
- [Standard Action: List](/list)

[long-running operation]: /long-running-operations

[URI path]: /paths

[paginated]: /pagination
[RFC 9110 Section 9.3.1]: https://datatracker.ietf.org/doc/html/rfc9110#section-9.3.1

[pagination]: /pagination
[safe]: /64#common-method-properties

[query parameters]: /query-parameters
[idempotent]: /64#common-method-properties

[Cache-Control]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control

Expand All @@ -122,16 +84,10 @@ consistency across paginated requests.

[304 Not Modified]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/304

[filtering]: /filtering

[200 OK]: /63#200-ok

[404 Not Found]: /63#404-not-found

[410 Gone]: /63#410-gone

## Changelog

* **2026-02-09**: Move this from AEP-131 to AEP-65. Extract `Individual Resources` section to `Fetch` action (new
AEP-131).Extract `Collection Resources` section to `List` action (new AEP-132).
* **2026-01-21**: Standardize HTTP status code references.
* **2025-11-12**: Initial AEP-131 for Thryv, adapted from [Google AIP-131][] and aep.dev [AEP-131][].

Expand Down
2 changes: 1 addition & 1 deletion aep/general/0065/aep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ id: 65
state: approved
slug: http-get
created: 2025-11-12
updated: 2026-01-21
updated: 2026-02-10
placement:
category: http
142 changes: 54 additions & 88 deletions aep/general/0131/aep.md
Original file line number Diff line number Diff line change
@@ -1,141 +1,107 @@
# Get
# Fetch

In REST APIs, it is customary to make a `GET` request to a resource's URI (for
In REST APIs, it is customary to make a [GET] request to a resource's URI (for
example, `/v1/publishers/{publisher_id}/books/{book_id}`) in order to retrieve
that resource.

Resource-oriented design AEP-121 honors this pattern through the `Get` method.
These RPCs accept the URI representing that resource and return the resource.
that resource. Resource-oriented design AEP-121 honors this pattern through the `Fetch` action.

## Guidance

- APIs **must** provide a get method for resources. The purpose of the get
method is to return data from a single resource.
- APIs **must** provide a `Fetch` action for resources. The purpose of the `Fetch`
action is to return data from a single resource.
- Some resources take longer to be retrieved than is reasonable for a regular
API request. In this situation, the API should use a
[long-running operation](/long-running-operations).

### Operation

{% tab proto %}

{% sample '../example.proto', 'rpc GetBook' %}

- The RPC's name **must** begin with the word `Get`. The remainder of the RPC
name **should** be the singular form of the resource's message name.
- The request message **must** match the RPC name, with a `Request` suffix.
- The response message **must** be the resource itself. (There is no
`GetBookResponse`.)
- The HTTP verb **must** be `GET`.
- The URI **should** contain a single variable field corresponding to the
resource path.
- This field **should** be called `path`.
- The URI **should** have a variable corresponding to this field.
- The `path` field **should** be the only variable in the URI path. All
remaining parameters **should** map to URI query parameters.
- There **must not** be a `body` key in the `google.api.http` annotation.
- There **should** be exactly one `google.api.method_signature` annotation,
with a value of `"path"`.

{% tab oas %}

`Get` operations **must** be made by sending a `GET` request to the resource's
URI:
`Fetch` operations **must** be made by sending a [GET] request to the resource's resource's canonical [URI path]:

```http
GET /v1/publishers/{publisher_id}/books/{book_id} HTTP/2
Host: bookstore.example.com
Accept: application/json
GET /v1/publishers/{publisher_id}/books/{book_id}
```

- The URI **should** contain a variable for each resource in the resource
hierarchy.
- The path parameter for all resource IDs **must** be in the form
`{resource-singular}` (such as `book`).

{% endtabs %}
`{resourceName}_id` (such as `book_id`), and path parameters representing
the ID of parent resources **must** end with `id`.

### Requests

{% tab proto %}

{% sample '../example.proto', 'message GetBookRequest' %}

- A resource path field **must** be included. It **should** be called `path`.
- The field **should** be annotated as `REQUIRED`.
- The field **should** identify the [resource type][aep-4] that it
references.
- The comment for the `path` field **should** document the resource pattern.
- The request message **must not** contain any other required fields, and
**should not** contain other optional fields except those described in
another AEP.
- The HTTP method **must** be [GET], and **must** follow the `GET` method guidelines in AEP-65.
- The request **must** be [safe] and **must not** have side effects.
- There **must not** be a request body.
- If a `GET` request contains a body, the body **must** be ignored, and
**must not** cause an error.
- The request **must not** _require_ any query parameters.
- Optional query parameters **may** be included (e.g., for [partial responses](/partial-responses))

**Note:** The `path` field in the request object corresponds to the `path`
variable in the `google.api.http` annotation on the RPC. This causes the `path`
field in the request to be populated based on the value in the URL when the
REST/JSON interface is used.
{% tab proto %}

{% tab oas %}

{% sample '../example.oas.yaml', '$.paths./publishers/{publisher_id}/books/{book_id}.get.parameters' %}

- The HTTP method **must** be `GET`.
- The request **must** be safe and **must not** have side effects.
- There **must not** be a request body.
- If a `GET` request contains a body, the body **must** be ignored, and
**must not** cause an error.
- The request **must not** require any fields in the query string. The request
**should not** include optional fields in the query string unless described
in another AEP.

{% endtabs %}

### Responses

The response **should** usually include the fully-populated resource unless
there is a reason to return a partial response (see AEP-157).
#### Successful Response

{% tab proto %}
A Fetch action **must** return a [200 OK] status code with the resource representation in the response body when the
resource exists.

The response content **must** be the resource itself (there is no `GetBookResponse`). The response **should** include
the fully populated resource unless there is a reason to return a partial response (see AEP-157).

{% sample '../example.proto', 'message Book' %}
{% tab proto %}

{% tab oas %}

{% sample '../example.oas.yaml', '$.paths./publishers/{publisher_id}/books/{book_id}.get.responses.200.content' %}

- The response content **must** be the resource itself. For example:
`#/components/schemas/Book`. The response **must** reference a schema with a
[`x-aep-resource` extension].

[`x-aep-resource` extension]: ./0004.md#annotating-resource-types

{% endtabs %}

### Errors
#### Error Responses

If the user does not have sufficient permission to know that the resource
exists, the service **should** reply with an HTTP 404 error, regardless of
whether or not the resource exists. Permission **must** be checked prior to
checking if the resource exists.
A Fetch action **must** return appropriate error responses. See [HTTP status codes] for a complete guide to error
handling.

If the user has sufficient permission to know that the resource exists, but is
unable to access it, the service **should** reply with an HTTP 403 error.
Most common error scenarios:

If the user does have proper permission, but the requested resource does not
exist, the service **must** reply with an HTTP 404 error.
- Return [404 Not Found] if the resource does not exist.
- If the resource previously existed and has since been deleted (e.g., soft-deleted), the server **may** instead
respond with [410 Gone], as described in AEP-164.
- See [authorization checks](/authorization) for details on responses based on permissions.

## Interface Definitions

{% tab proto -%}

{% sample '../example.proto', 'rpc GetBook' %}

{% sample '../example.proto', 'message GetBookRequest' %}

{% sample '../example.proto', 'message Book' %}

{% tab oas %}

{% sample '../example.oas.yaml', '$.paths./publishers/{publisher_id}/books/{book_id}.get' %}

{% endtabs %}

## Changelog

* **2026-02-09**: Initial AEP-131, adapted from [Google AIP-131][] and aep.dev [AEP-131][].

[Google AIP-131]: https://google.aip.dev/131

[AEP-131]: https://aep.dev/131

[GET]: /http-get

[URI path]: /paths

[safe]: /64#common-method-properties

[HTTP status codes]: /status-codes

[200 OK]: /63#200-ok

[404 Not Found]: /63#404-not-found

[410 Gone]: /63#410-gone
2 changes: 1 addition & 1 deletion aep/general/0131/aep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
id: 131
state: approved
created: 2026-02-09
updated: 2026-02-09
updated: 2026-02-10
slug: fetch
placement:
category: actions
Expand Down
Loading