Skip to content

API Portal

Traefik Enterprise includes an API Portal which groups all the API specifications from your services into a web UI, if they support the OpenAPI format (formerly known as Swagger).

It works by looking for a JSON file on the service endpoint, which should match the file name defined in the configuration, and making it available on the API Portal web app. It does this for all services that expose an API specification file.

The API specifications also allows your services to be tested directly from within the API Portal.

API Portal page

Traefik Enterprise can also generate multiple API Portals, each exposing a subset of your APIs.

Configuration

In order to enable the API Portal feature, a path property must be defined in the static configuration.

API Portal Options

path

Required, Default=""

The path option must be a string representing the name of the specification file to look for on the service endpoint. For example, if spec.json is defined as path, the API Portal will try to get this file under the service URL. Thus, the path <service-url>/spec.json must point to the specification file.

apiportal:
  path: spec.json
[apiportal]
  path = "spec.json"

Query parameters are allowed and will be included on the request call to the service, for example /spec/api.yaml?variant=b is a valid path.

It's also possible to define the API spec path on the dynamic configuration, declared on the service definition attached to your router. Doing so overrides the path specified on the static configuration.

hideServiceNames

Required, Default="false"

The hideServiceNames option determines whether the service names are shown in the API specifications list on the left side menu of the API Portal.

apiportal:
  hideServiceNames: true
[apiportal]
  hideServiceNames = true

API Portal Service Configuration

API portal can be further configured on each service that exposes one or more Open API specifications.

path

Optional, Default=""

Overwrites the Open API specification path set in the static configuration for this service.

labels:
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.path=/path/to/spec.json"
apiVersion: v1
kind: Service
metadata:
  name: myapi-svc
  annotations:
    traefik.ingress.kubernetes.io/service.apiportal.path: /path/to/spec.json

spec:
  ports:
    - name: web
      port: 80
  selector:
    app: traefiklabs
    task: whoami
- "traefik.http.services.myapi-svc.loadbalancer.apiportal.path=/path/to/spec.json"
"labels": {
    "traefik.http.services.myapi-svc.loadbalancer.apiportal.path": "/path/to/spec.json"
}
labels:
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.path=/path/to/spec.json"
http:
  services:
    myapi-svc:
      loadbalancer:
        apiportal:
          path: /path/to/spec.json
[http.services.myapi-svc]
  [http.services.myapi-svc.loadbalancer.apiportal]
    path = "/path/to/spec.json"

groups

Optional, Default=None

You can define in which API Portal a service should expose its API specification by annotating it with the following label. Traefik Enterprise dynamically creates new API Portals for each group referenced this way.

Path to the endpoint serving the API specification file can be configured for each group. Groups that do not set an explicit path default to the path of the service if set, or to the one defined in the static configuration otherwise.

labels:
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.firstGroup={}"
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.secondGroup.path=/somewhere/spec.json"
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.thirdGroup.path=/elsewhere/spec.json"
apiVersion: v1
kind: Service
metadata:
  name: myapi-svc
  annotations:
    traefik.ingress.kubernetes.io/service.apiportal.groups.firstGroup: ""
    traefik.ingress.kubernetes.io/service.apiportal.groups.secondGroup.path: /somewhere/spec.json
    traefik.ingress.kubernetes.io/service.apiportal.groups.thirdGroup.path: /elsewhere/spec.json

spec:
  ports:
    - name: web
      port: 80
  selector:
    app: traefiklabs
    task: whoami
- "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.firstGroup={}"
- "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.secondGroup.path=/somewhere/spec.json"
- "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.thirdGroup.path=/elsewhere/spec.json"
"labels": {
    "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.firstGroup": {},
    "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.secondGroup.path": "/somewhere/spec.json",
    "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.thirdGroup.path": "/elsewhere/spec.json"
}
labels:
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.firstGroup={}"
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.secondGroup.path=/somewhere/spec.json"
  - "traefik.http.services.myapi-svc.loadbalancer.apiportal.groups.thirdGroup.path=/elsehwere/spec.json"
http:
  services:
    myapi-svc:
      loadbalancer:
        apiportal:
          groups:
            firstGroup: {}
            secondGroup:
              path: /somewhere/spec.json
            thirdGroup:
              path: /elsewhere/spec.json
[http.services.myapi-svc]
  [http.services.myapi-svc.loadbalancer.apiportal.groups.firstGroup]
  [http.services.myapi-svc.loadbalancer.apiportal.groups.secondGroup]
    path = "/somewhere/spec.json"
  [http.services.myapi-svc.loadbalancer.apiportal.groups.thirdGroup]
    path = "/elsewhere/spec.json"

Default Group

Note that all API specifications are always exposed in the default API Portal, regardless of whether they have an explicit group defined or not.

Routing Traffic to API Portals

Where is the API Portal served?

Just like the Dashboard, the API Portals are served by Ingress proxies.

Traefik Enterprise creates internal services for each group of APIs you defined. They are named apiportal-$GROUP_NAME@internal. An additional default service called apiportal@internal serves all API specifications, regardless of whether they have an explicit group defined or not.

It's then possible to use all of Traefik's routing capabilities to build the most suitable configuration to expose these API Portal services.

Example

This example shows how to enable the API Portal on port 8888 of the domain apiportal.domain.org.

To do so, create a router through the dynamic configuration that routes all requests coming through the internal entrypoint to the apiportal@internal service. In our case, the entrypoint internal is listening to the address :8888.

First, the applied static configuration should contain the following elements:

# [...]
entrypoints:
  # [...]
  internal:
    address: ":8888"

apiportal:
  path: spec.json
# [...]
[entryPoints]
  # [...]
  [entryPoints.internal]
    address = ":8888"

[apiportal]
  path = "spec.json"

Using the teectl apply command:

teectl apply --file=static.yaml
teectl apply --file=static.toml

Then, apply the following dynamic configuration:

labels:
  - "traefik.http.routers.apiportal.rule=Host(`apiportal.domain.org`)"
  - "traefik.http.routers.apiportal.service=apiportal@internal"
  - "traefik.http.routers.apiportal.entryPoints=internal"
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: apiportal
spec:
  entryPoints:
    - internal
  routes:
    - match: Host(`apiportal.domain.org`)
      kind: Rule
      services:
        - name: apiportal@internal
          kind: TraefikService
- "traefik.http.routers.apiportal.rule=Host(`apiportal.domain.org`)"
- "traefik.http.routers.apiportal.service=apiportal@internal"
- "traefik.http.routers.apiportal.entryPoints=internal"
"labels": {
    "traefik.http.routers.apiportal.rule": "Host(`apiportal.domain.org`)",
    "traefik.http.routers.apiportal.service": "apiportal@internal",
    "traefik.http.routers.apiportal.entryPoints": "internal"
}
labels:
  - "traefik.http.routers.apiportal.rule=Host(`apiportal.domain.org`)"
  - "traefik.http.routers.apiportal.service=apiportal@internal"
  - "traefik.http.routers.apiportal.entryPoints=internal"
http:
  routers:
    apiportal:
      rule: Host(`apiportal.domain.org`)
      service: apiportal@internal
      entryPoints:
        - internal
[http.routers.apiportal]
  rule = "Host(`apiportal.domain.org`)"
  service = "apiportal@internal"
  entryPoints = ["internal"]

Using the teectl apply command:

teectl apply --file=dynamic.yaml
teectl apply --file=dynamic.toml

At this point, the API Portal is ready to expose specifications from any service on your network, and the web app is available at apiportal.domain.org. There are some examples of valid JSON files on the OpenAPI specification repository.