For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Create ApiProducts
Bundle your APIs into versioned ApiProducts and expose them in the portal catalog.
Note
This guide must be completed by a Portal admin.
An ApiProduct is a logical API offering that groups one or more versions of an API. Each version references an HTTPRoute that serves that version’s traffic. The portal controller automatically links the HTTPRoute’s backend services to their ApiDocs and stitches the schemas together into a single generated ApiDoc per version so that they can be rendered in the portal frontend.
You do not reference ApiDocs directly in an ApiProduct. The controller discovers them implicitly through the HTTPRoute’s backend services as shown in this diagram.
flowchart LR
APV[ApiProduct Version] -->|targetRefs| HR[HTTPRoute]
HR -->|backendRefs| Svc[Service]
AD[ApiDoc] -->|servedBy| Svc
APV -.->|controller generates| SAD[Stitched ApiDoc]
- An ApiProduct version references one or more HTTPRoutes via the
targetRefsfield. - The portal controller examines each HTTPRoute’s
backendRefsto find the backend services. - The portal controller finds the ApiDocs that are served by these services by using the
servedByfield. - The portal controller stitches the matching schemas together into a single generated ApiDoc per version.
Before you begin
- Follow the Get started guide to install Solo Enterprise for kgateway.
- Set up a portal.
- Create an ApiDoc for your service. The example in this guide uses the petstore app.
Create an ApiProduct
Create an ApiProduct and define one or more versions of your API. Each version references the HTTPRoute that serves that version of the API.
Single API version
Create an ApiProduct with a single version of the petstore API. The ApiProduct references the petstore HTTPRoute that you created before you began.
kubectl apply -f- <<EOF
apiVersion: portal.solo.io/v1alpha1
kind: ApiProduct
metadata:
name: petstore-api
namespace: default
spec:
id: petstore
displayName: "Petstore API"
description: "A sample API for managing pets."
contactEmail: "support@example.com"
customMetadata:
category: "Pet Management"
versions:
- name: v1
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: petstore-route
openApiMetadata:
title: "Petstore API"
description: "Manage your pets"
termsOfService: "https://example.com/terms"
contact: "support@example.com"
license: "Apache-2.0"
customMetadata:
environment: "production"
EOF| Setting | Description |
|---|---|
id | A URL-safe unique identifier for the ApiProduct (1–128 characters). This ID is used to construct the API URL in the portal API catalog. |
displayName | Human-readable name for that API that is displayed in the portal UI. |
description | Optional description of the API product (1–1024 characters) displayed in the portal UI. |
contactEmail | Optional contact email address (max 256 characters) displayed in the portal UI for questions about this API product. |
customMetadata | Optional arbitrary key-value pairs that are surfaced in the portal UI. You can have a maximum of 16 entries. |
versions[].name | The version identifier, such as v1 or v2. |
versions[].targetRefs | Reference the HTTPRoutes that serve this version. |
versions[].customMetadata | Optional arbitrary key-value pairs of custom metadata for this specific version, surfaced in the portal UI. You can have a maximum of 16 entries. |
versions[].openApiMetadata | Optional metadata merged into the stitched OpenAPI schema for this version and displayed in the portal UI when you select this API version. |
versions[].openApiMetadata.title | Optional title of the API version (1–256 characters), mapped to info.title in the stitched OpenAPI schema. |
versions[].openApiMetadata.description | Optional description of the API version (1–1024 characters), mapped to info.description in the stitched OpenAPI schema. |
versions[].openApiMetadata.termsOfService | Optional URL to the terms of service for this API version (1–512 characters), mapped to info.termsOfService in the stitched OpenAPI schema. |
versions[].openApiMetadata.contact | Optional contact information for this API version (1–256 characters). A value that parses as an email is used as info.contact.email; a value that parses as a URL is used as info.contact.url; any other value is used as info.contact.name. |
versions[].openApiMetadata.license | Optional license name or SPDX identifier for this API version (1–256 characters), such as MIT or Apache-2.0. Mapped to info.license.name in the stitched OpenAPI schema. |
Multiple API versions
An ApiProduct can expose multiple API versions simultaneously. Each version references its own HTTPRoute independently. The portal UI displays a version selector for products with multiple versions.
Create a second HTTPRoute for the
v2version of the API. Make sure to use a unique matcher so that requests can be correctly routed to this version. The matcher must be different from the matcher that you use for thev1version of the API.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: petstore-v2-route namespace: default spec: parentRefs: - name: portal-gateway namespace: default hostnames: - "api.example.com" rules: - matches: - path: type: PathPrefix value: /petstore/v2 filters: - type: URLRewrite urlRewrite: path: type: ReplacePrefixMatch replacePrefixMatch: / backendRefs: - name: petstore port: 8080 EOFCreate the ApiProduct and include both versions of your API.
kubectl apply -f- <<EOF apiVersion: portal.solo.io/v1alpha1 kind: ApiProduct metadata: name: petstore-api namespace: default spec: id: petstore displayName: "Petstore API" versions: - name: v1 targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: petstore-route openApiMetadata: title: "Petstore API v1" description: "Manage your pets" - name: v2 targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: petstore-v2-route openApiMetadata: title: "Petstore API v2" description: "Manage your pets (v2)" EOFVerify that a stichted ApiDoc is generated for each version of the API. Each version gets its own generated ApiDoc named
<apiproduct-name>-<version-name>.kubectl get apidocs -AExample output:
NAMESPACE NAME SOURCE READY AGE default petstore-api-v1 Stitched True 1m default petstore-api-v2 Stitched True 1m default petstore-url-apidoc Url True 1m
Add the ApiProduct to the portal
Update the Portal resource to include the ApiProduct in its catalog. The portal controller regenerates the PortalConfig after you update the Portal.
Reference an ApiProduct in the same namespace as the Portal.
kubectl apply -f- <<EOF
apiVersion: portal.solo.io/v1alpha1
kind: Portal
metadata:
name: my-portal
namespace: default
spec:
parametersRef:
name: portal-params
visibility:
public: true
apiProductRefs:
- name: petstore-api
- name: httpbin-api
EOFReference an ApiProduct in a different namespace by specifying the namespace field. Cross-namespace references require a ReferenceGrant in the target namespace to authorize the reference.
Create a ReferenceGrant in the namespace where the ApiProduct lives (
other-namespace) to allow the Portal in thedefaultnamespace to reference it.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: portal-apiproduct-grant namespace: other-namespace spec: from: - group: portal.solo.io kind: Portal namespace: default to: - group: portal.solo.io kind: ApiProduct EOFCreate the Portal and reference the ApiProduct in
other-namespace.kubectl apply -f- <<EOF apiVersion: portal.solo.io/v1alpha1 kind: Portal metadata: name: my-portal namespace: default spec: parametersRef: name: portal-params visibility: public: true apiProductRefs: - name: petstore-api namespace: other-namespace - name: httpbin-api EOF
Include all ApiProducts in a specific namespace by using a wildcard for the name field.
kubectl apply -f- <<EOF
apiVersion: portal.solo.io/v1alpha1
kind: Portal
metadata:
name: my-portal
namespace: default
spec:
parametersRef:
name: portal-params
visibility:
public: true
apiProductRefs:
- name: "*"
namespace: default
EOFReference a specific ApiProduct across all namespaces by setting namespace: "*". Cross-namespace products still require a ReferenceGrant in each target namespace. Products in namespaces without a grant are silently skipped.
Create a ReferenceGrant in each namespace that the Portal should be allowed to access.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: portal-apiproduct-grant namespace: team-a spec: from: - group: portal.solo.io kind: Portal namespace: default to: - group: portal.solo.io kind: ApiProduct EOFCreate the Portal with a namespace wildcard.
kubectl apply -f- <<EOF apiVersion: portal.solo.io/v1alpha1 kind: Portal metadata: name: my-portal namespace: default spec: parametersRef: name: portal-params visibility: public: true apiProductRefs: - name: petstore-api namespace: "*" EOFReview the Portal status to monitor which namespaces could not be added to the catalog due to missing ReferenceGrants.
kubectl describe portal my-portal -n default
Include all ApiProducts across all namespaces by setting both
nameandnamespaceto"*". You still need a ReferenceGrant for each namespace. ApiProducts in unauthorized namespaces are silently skipped.kubectl apply -f- <<EOF apiVersion: portal.solo.io/v1alpha1 kind: Portal metadata: name: my-portal namespace: default spec: parametersRef: name: portal-params visibility: public: true apiProductRefs: - name: "*" namespace: "*" EOFReview the Portal status to monitor which namespaces could not be added to the catalog due to missing ReferenceGrants.
kubectl describe portal my-portal -n default
Verify your ApiProduct
List the ApiProducts and ApiDocs in your namespace. For each ApiProduct version, the controller generates a stitched ApiDoc that is named
<apiproduct-name>-<version-name>.kubectl get apiproduct,apidoc -n defaultExample output:
NAME ID DISPLAY NAME READY apiproduct.portal.solo.io/petstore-api petstore Petstore API True NAME SOURCE READY AGE apidoc.portal.solo.io/petstore-api-v1 Stitched True 24m apidoc.portal.solo.io/petstore-api-v2 Stitched True 7m21s apidoc.portal.solo.io/petstore-url-apidoc Url True 22hIf an ApiProduct does not show
Ready=True, describe the resource to see the error details.kubectl describe apiproduct petstore-api -n defaultVerify that the PortalConfig was updated with the ApiProduct. The
spec.apisfield must contain an entry for each ApiProduct version and a reference to the generated stitched ApiDoc resource.kubectl get portalconfig my-portal -n default -o yamlExample output:
... spec: apis: - apiDocRef: name: petstore-api-v1 namespace: default apiProductDisplayName: Petstore API apiProductId: petstore apiProductDescription: A sample API for managing pets. contact: support@example.com apiVersion: v1 description: Manage your pets title: Petstore API v1 - apiDocRef: name: petstore-api-v2 namespace: default apiProductDisplayName: Petstore API apiProductId: petstore apiProductDescription: A sample API for managing pets. contact: support@example.com apiVersion: v2 description: Manage your pets (v2) title: Petstore API v2 - apiDocRef: name: httpbin-api-v1 namespace: default apiProductCustomMetadata: category: Utilities apiProductDisplayName: HTTPBin API apiProductId: httpbin apiVersion: v1 description: A simple HTTP request/response service for testing title: HTTPBin API portalMetadata: name: my-portal