AIP-132
Standard methods: List
In many APIs, it is customary to make a GET request to a collection's URI
(for example, /v1/invoices) in order to retrieve a list of
resources, each of which lives within that collection.
Resource-oriented design (AIP-121) honors this pattern through the List
method. These RPCs accept the parent collection (and potentially some other
parameters), and return a list of responses matching that input.
Guidance
APIs must provide a List method for resources. The purpose of the List
method is to return data from a finite collection.
List methods are specified using the following pattern:
rpc ListInvoices(ListInvoicesRequest) returns (ListInvoicesResponse);
- The RPC's name must begin with the word
List. The remainder of the RPC name should be the plural form of the resource being listed. - The request and response messages must match the RPC name, with
RequestandResponsesuffixes. - The HTTP verb must be
GET. - The collection whose resources are being listed should map to the URI
path.
- All parameters must map to URI query parameters.
- The collection identifier (
invoicesin the above example) must be a literal string.
- The
bodykey in the HTTP request must be omitted.
Request message
List methods implement a common request message pattern:
message ListInvoicesRequest {
// Pagination parameters
common.PaginationRequest pagination = 1
(google.api.field_behavior) = REQUIRED,
(common.api).http.embedded = true
];
}
- The request message must include a
common.PaginationRequestfield to support pagination. For more information, see AIP-158.- The pagination field must have the
(common.api).http.embeddedannotation, which exposes pagination fields as top-level query parameters. - The pagination field must have the
(google.api.field_behavior) = REQUIREDannotation to ensure clients don't forget to include pagination in gRPC calls, while still allowing HTTP requests without pagination parameters.
- The pagination field must have the
- The request message must not contain any other required fields, and may contain optional filtering fields as described in the filtering section.
Note: List methods should return the same results for any user that has permission to make a successful List request on the collection and identical resource access scope.
Response message
List methods implement a common response message pattern:
message ListInvoicesResponse {
// The resource type being returned.
string object = 1 [
(google.api.field_behavior) = REQUIRED,
(buf.validate.field).string.const = "list"
];
// The invoices returned.
repeated Invoice data = 2 [(google.api.field_behavior) = OPTIONAL];
// Pagination information
common.PaginationResponse pagination = 3 [(google.api.field_behavior) = REQUIRED];
}
- The response message must include an
objectwith valuelistand have the(google.api.field_behavior) = REQUIREDannotation. - The response message must include one repeated field named
datacorresponding to the resources being returned, have the(google.api.field_behavior) = OPTIONALannotation, and should not include any other repeated fields.- The response should usually include fully-populated resources unless there is a reason to return a partial response (see AIP-157).
- The response message should include a
common.PaginationResponsefield to support pagination with the(google.api.field_behavior) = REQUIREDannotation. For more information, see AIP-158.
Ordering
List methods must return resources in a fixed order: reverse chronological
by created_attimestamp (most recent first), with id as a secondary sort key.
Client-specified sorting is not supported.
Filtering
List methods may allow clients to specify filters; if they do, the request message shouldinclude appropriate filter fields. Filtering is described in more detail in AIP-160.
message ListInvoicesRequest {
// Pagination parameters
// Filter parameters
repeated string store_id = 2 [(google.api.field_behavior) = OPTIONAL];
repeated string customer_id = 3 [(google.api.field_behavior) = OPTIONAL];
google.protobuf.Timestamp created_after = 4 [(google.api.field_behavior) = OPTIONAL];
google.protobuf.Timestamp created_before = 5 [(google.api.field_behavior) = OPTIONAL];
}
When defining filter fields, the following rules must be applied:
- Filter fields must only correspond to fields that exist on the resource
object, with field names matching exactly except in cases where direct
representation is not possible (e.g., date ranges like
created_after,created_before). - All filter fields must be annotated with
[(google.api.field_behavior) = OPTIONAL]. - Fields that may accept multiple values should use the
repeatedkeyword and must be named in the singular form.
Note: Due to the absence of a comprehensive filtering or search query language, filtering capabilities are intentionally restricted to specific fields. This approach ensures consistency and predictability across APIs while simplifying implementation.
Handling Zero-Value Fields
Fields where the zero value has semantic meaning (e.g., bool, enum) should use the optional
keyword in the request message:
optional bool paid = 6 [(google.api.field_behavior) = OPTIONAL];
When a field is marked as optional, a nil value indicates that no filtering
is applied on that field.
HTTP Request Semantics
The HTTP request semantics for filter fields follow these rules:
- A request without a specific filter field in the query parameters must return results without filtering on that field.
- A request with a filter field set to a specific value must return only resources where that field matches the specified value.
- Filtering on the
unspecifiedvalue of enums is not supported.
Soft-deleted resources
Some APIs need to "soft delete" resources, marking them as deleted or pending deletion (and optionally purging them later).
APIs that do this should not include deleted resources by default in list
requests. APIs with soft deletion of a resource should include a
bool show_deleted field in the list request that, if set, will cause
soft-deleted resources to be included.
Errors
See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors.
Rationale
Enum filtering on unspecified
The tension between using optional for enum fields while not supporting
filtering on the unspecified value stems from conflicting interpretations
of null in different contexts. In JSON responses, as described
in AIP-126, unspecified enum values are serialized as null.
However, in filtering contexts, the absence of a parameter means "don't
filter on this field," creating an ambiguity when a client explicitly
requests ?status=null - should this mean "filter for resources with
unspecified status" or "don't filter on status"?
This semantic inconsistency has prevented implementation of filtering on unspecified enum values for now. The current design prioritizes consistency in filter parameter interpretation until a more intuitive approach can be identified.
History
Divergence from Google AIP
The List method implementation diverges from Google's AIP-132 by using
structured request/response objects for pagination through common.PaginationRequest
and common.PaginationResponse instead of direct page token fields.
This creates a consistent pattern across all paginated endpoints.
The response format uses a standardized structure with object and data
fields rather than resource-specific field names, enabling generic client
handling across all collection endpoints.
This AIP implements typed filter fields for specific resources instead of a generic string filter query language, prioritizing type safety and explicit filtering capabilities over query flexibility.
Further reading
- For details on pagination, see AIP-158.
Changelog
2025-06-12: Forked AIP-132 and added a divergence from Google AIP section.