Skip to main content


The public-api plugin exposes an internal API endpoint, making it publicly accessible. One of the primary use cases of this plugin is to expose internal endpoint created by other plugins.


The examples below demonstrate how you can configure public-api in different scenarios.

Implement JWT for Consumer Authentication

The following example demonstrates how you can expose the JWT signing endpoint /apisix/plugin/jwt/sign, which is added by the jwt-auth plugin, and implement JWT for consumer authentication.

Create a route with the public-api plugin:

curl "" -X PUT \
-d '{
"id": "public-jwt-sign",
"uri": "/apisix/plugin/jwt/sign",
"plugins": {
"public-api": {}

❶ When the plugin uri parameter is not configured, the route uri will be exposed.

Note that at this stage, the jwt-auth plugin has not been enabled anywhere, so if you send a request to the signing endpoint, you are expected to get a 404 Not Found.

Create a consumer with jwt-auth plugin:

curl "" -X PUT \
-d '{
"username": "jack",
"plugins": {
"jwt-auth": {
"key": "jack-key"

Create a route with jwt-auth plugin:

curl "" -X PUT \
-d '{
"id": "jwt-route",
"uri": "/headers",
"plugins": {
"jwt-auth": {}
"upstream": {
"type": "roundrobin",
"nodes": {
"": 1

Send a request to the signing endpoint to get JWT:

jwt_token=$(curl -s "") && echo $jwt_token

You should see a token similar to the following:


Send a request to the route with the JWT in the Authorization header:

curl -i "" -H "Authorization: ${jwt_token}"

You should receive an HTTP/1.1 200 OK response similar to the following:

"headers": {
"Accept": "*/*",
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY5NTAyOTUxMX0.jdZ2iGtXqEMW6QIECTz8CWjBtLt3UMFS9R2j6dVuPJM",
"Host": "",
"User-Agent": "curl/7.74.0",
"X-Amzn-Trace-Id": "Root=1-65081904-5a1f18143c29bd2d7d6be0d7",
"X-Forwarded-Host": ""

Expose Prometheus Metrics at Custom Endpoint

The following example demonstrates how you can disable the Prometheus export server that, by default, exposes an endpoint on port 9091, and expose APISIX Prometheus metrics on a new public API endpoint on port 9080, which APISIX uses to listen to other client requests.

You will also configure the route such that the internal endpoint /apisix/prometheus/metrics is exposed at a custom endpoint.


If a large quantity of metrics are being collected, the plugin could take up a significant amount of CPU resources for metric computations and negatively impact the processing of regular requests.

To address this issue, APISIX uses privileged agent and offloads the metric computations to a separate process. This optimization applies automatically if you use the metric endpoint configured in the configuration files, as demonstrated above. If you expose the metric endpoint with the public-api plugin, you will not benefit from this optimization.

Disable the Prometheus export server in the configuration file and reload APISIX for changes to take effect:

enable_export_server: false

Next, create a route with public-api plugin and expose a public API endpoint for APISIX metrics:

curl "" -X PUT \
-d '{
"uri": "/prometheus_metrics",
"plugins": {
"public-api": {
"uri": "/apisix/prometheus/metrics"

❶ Set the route uri to the custom endpoint path.

❷ Set the plugin uri to the internal endpoint to be exposed.

Send a request to the custom metrics endpoint:

curl ""

You should see an output similar to the following:

# HELP apisix_http_requests_total The total number of client requests since APISIX started
# TYPE apisix_http_requests_total gauge
apisix_http_requests_total 1
# HELP apisix_nginx_http_current_connections Number of HTTP connections
# TYPE apisix_nginx_http_current_connections gauge
apisix_nginx_http_current_connections{state="accepted"} 1
apisix_nginx_http_current_connections{state="active"} 1
apisix_nginx_http_current_connections{state="handled"} 1
apisix_nginx_http_current_connections{state="reading"} 0
apisix_nginx_http_current_connections{state="waiting"} 0
apisix_nginx_http_current_connections{state="writing"} 1

Protect Public Endpoint with Authentication

The following example demonstrates how you can use an authentication plugin to secure the publicly exposed endpoint.

Before proceeding, please ensure that you have completed the steps in the Implement JWT for Consumer Authentication example, where the jwt-auth plugin is configured and the signing endpoint is exposed.

Create a consumer with key-auth plugin:

curl "" -X PUT \
-d '{
"username": "jwt_sign_admin",
"plugins": {
"key-auth": {
"key": "jwt-sign-admin-pwd"

Update the route with key-auth so that only the authenticated requests can access the signing endpoint:

curl "" -X PATCH \
-d '{
"plugins": {
"key-auth": {}

To verify, send a request to the public signing endpoint without the authentication key:

curl -i ""

You should receive an HTTP/1.1 401 Unauthorized response.

Send a request to the public signing endpoint with the authentication key:

curl -i "" -H "apikey: jwt-sign-admin-pwd"

You should receive an HTTP/1.1 200 OK response and see a token similar to the following:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDYzMzQxMjMsImtleSI6ImphY2sta2V5In0.wjSrbMF0JAkJUk5BKFonwkwkeWTKvonKGdhE Logo

API Management for Modern Architectures with Edge, API Gateway, Kubernetes, and Service Mesh.


API7 Cloud

SOC2 Type IRed Herring

Copyright © APISEVEN Ltd. 2019 – 2024. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the

Apache Software Foundation