This AIP is currently a draft. This means that it is being actively debated and discussed, and it may change in non-trivial ways.

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 Request and Response suffixes.
  • 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 (invoices in the above example) must be a literal string.
  • The body key 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.PaginationRequest field to support pagination. For more information, see AIP-158.
    • The pagination field must have the (common.api).http.embedded annotation, which exposes pagination fields as top-level query parameters.
    • The pagination field must have the (google.api.field_behavior) = REQUIRED annotation to ensure clients don't forget to include pagination in gRPC calls, while still allowing HTTP requests without pagination parameters.
  • 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 object with value list and have the (google.api.field_behavior) = REQUIRED annotation.
  • The response message must include one repeated field named data corresponding to the resources being returned, have the (google.api.field_behavior) = OPTIONAL annotation, 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.PaginationResponse field to support pagination with the (google.api.field_behavior) = REQUIRED annotation. 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 repeated keyword 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 unspecified value 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.