Please select the area the issue is related to
Platform API
Please select the aspect the issue is related to
Aspect/API (API backends, definitions, contracts, interfaces, OpenAPI)
Suggested Improvement
Current limitation
GET /api/v0.9/rest-apis (ListRESTAPIs) returns RESTAPIListResponse, whose list items are the full RESTAPI schema, the same payload as the single-resource detail endpoint GET /rest-apis/{restApiId}:
platform-api/resources/openapi.yaml
RESTAPIListResponse:
properties:
list:
type: array
items:
$ref: '#/components/schemas/RESTAPI' # full detail schema
That means every item in a listing carries the entire API definition:
operations[] — every resource/method with its own policies[], scopes, auth config, etc.
policies[] — the full API-level policy chain with params
upstream — backend URL(s), auth/TLS configuration, resolved {{ secret "..." }} references
channels[], subscriptionPlans[], transport[]
A listing view only needs identity/summary information: id, displayName, description, context, version, projectId, lifeCycleStatus, kind, readOnly, createdBy, createdAt, updatedAt.
Impact
- Response size / latency. An API with 50–100 operations, each with its own policy list, produces a very large object. Multiply by
limit and a single listing request returns megabytes of JSON that no list UI renders. This is the payload the API listing page in the control-plane portal and ap CLI fetch on every page load.
- Wasted DB and CPU work. Full
configuration blobs are read from the DB and JSON-unmarshalled for every row, only to be discarded by the caller.
- N+1 project lookup.
modelToRESTAPIUnresolved calls projectRepo.GetProjectByUUID once per API in the loop just to resolve projectId to a project handle, even though the listing is already filtered to a single project (projectId is a required query parameter). One resolution per page would suffice.
- Over-exposure of configuration detail. Backend upstream URLs, auth configuration, and full policy parameters are returned to anyone holding
ap:rest_api:read, on an endpoint that is meant to enumerate APIs. Detail-level configuration should be fetched deliberately via the detail endpoint.
Notably, updatedBy is already being stripped from list responses in the service layer (apiResponse.UpdatedBy = nil) with the OpenAPI description noting it is "Only present in the detail response"; a field-by-field workaround that shows the list and detail representations have already diverged in practice, just without a schema to express it.
Suggested improvement
Introduce a dedicated RESTAPIListItem schema for the listing response, following the pattern already established elsewhere in the same spec:
MCPProxyListItem → used by MCPProxyListResponse
LLMProxyListItem → used by LLMProxyListResponse
LLMProviderListItem → used by LLMProviderListResponse
SecretSummary → used by SecretListResponse
REST APIs are the outlier still returning the full detail schema in a collection response.
Proposed shape:
RESTAPIListItem:
type: object
required:
- displayName
- context
- version
- projectId
properties:
id: { type: string }
displayName: { type: string }
description: { type: string }
context: { type: string }
version: { type: string }
projectId: { type: string }
kind: { type: string }
lifeCycleStatus: { type: string, enum: [STAGED, CREATED, PUBLISHED, DEPRECATED, RETIRED, BLOCKED] }
readOnly: { type: boolean, readOnly: true }
createdBy: { type: string, readOnly: true }
createdAt: { type: string, format: date-time, readOnly: true }
updatedAt: { type: string, format: date-time, readOnly: true }
RESTAPIListResponse:
properties:
list:
type: array
items:
$ref: '#/components/schemas/RESTAPIListItem'
Related Issues
#3391
Please select the area the issue is related to
Platform API
Please select the aspect the issue is related to
Aspect/API (API backends, definitions, contracts, interfaces, OpenAPI)
Suggested Improvement
Current limitation
GET /api/v0.9/rest-apis(ListRESTAPIs) returnsRESTAPIListResponse, whoselistitems are the fullRESTAPIschema, the same payload as the single-resource detail endpointGET /rest-apis/{restApiId}:platform-api/resources/openapi.yamlThat means every item in a listing carries the entire API definition:
operations[]— every resource/method with its ownpolicies[], scopes, auth config, etc.policies[]— the full API-level policy chain withparamsupstream— backend URL(s), auth/TLS configuration, resolved{{ secret "..." }}referenceschannels[],subscriptionPlans[],transport[]A listing view only needs identity/summary information:
id,displayName,description,context,version,projectId,lifeCycleStatus,kind,readOnly,createdBy,createdAt,updatedAt.Impact
limitand a single listing request returns megabytes of JSON that no list UI renders. This is the payload the API listing page in the control-plane portal andapCLI fetch on every page load.configurationblobs are read from the DB and JSON-unmarshalled for every row, only to be discarded by the caller.modelToRESTAPIUnresolvedcallsprojectRepo.GetProjectByUUIDonce per API in the loop just to resolveprojectIdto a project handle, even though the listing is already filtered to a single project (projectIdis a required query parameter). One resolution per page would suffice.ap:rest_api:read, on an endpoint that is meant to enumerate APIs. Detail-level configuration should be fetched deliberately via the detail endpoint.Notably,
updatedByis already being stripped from list responses in the service layer (apiResponse.UpdatedBy = nil) with the OpenAPI description noting it is "Only present in the detail response"; a field-by-field workaround that shows the list and detail representations have already diverged in practice, just without a schema to express it.Suggested improvement
Introduce a dedicated
RESTAPIListItemschema for the listing response, following the pattern already established elsewhere in the same spec:MCPProxyListItem→ used byMCPProxyListResponseLLMProxyListItem→ used byLLMProxyListResponseLLMProviderListItem→ used byLLMProviderListResponseSecretSummary→ used bySecretListResponseREST APIs are the outlier still returning the full detail schema in a collection response.
Proposed shape:
Related Issues
#3391