Skip to content

OpenFaaS REST API

The OpenFaaS REST API along with the Kubernetes CRDs (Function, Profile, JwtIssuer, Policy, Role and Secret) are the primary way to interact with functions.

Learning with the faas-cli

The faas-cli is the original client for the REST API. The source code is available on GitHub at: openfaas/faas-cli. One of the easiest ways to develop programs for OpenFaaS is to try out the faas-cli commands that you already know, with the FAAS_DEBUG=1 environment variable set.

It'll show the HTTP Path, Method and Query String, Body and any additional headers used so that you can build your own integration.

A quick note on TLS: when you expose OpenFaaS over the Internet, you should enable HTTPS to prevent snooping and tampering.

Documentation

The API documentation is written in OpenAPI and is available on GitHub:

See also: spec.openapi.yml

Note that multiple namespaces are not supported in the Community Edition or Standard Edition of OpenFaaS. There may be additional constraints with the Community Edition, so make sure you review the comparison table.

SDKs

There is an official Go SDK which is used in the OpenFaaS event connectors and auto-scaler.

The goals of this SDK are to be lightweight, and intuitive to use, whilst using the same API types that the OpenFaaS gateway and provider use from the faas-provider's type package.

See also: Go types used in the OpenFaaS API

You can generate a client for Node.js, Python, Java and so forth by using the OpenAPI specification available on GitHub, or you could write simple HTTP calls.

The API is designed so that you can write HTTP calls by hand and move very quickly.

In-cluster vs local access

The OpenFaaS REST API can be accessed from within the cluster or from outside of the cluster.

When accessing the API for development, you may want to port-forward the OpenFaaS gateway to your local machine via kubectl port-forward. This talks to the Kubernetes API server so is encrypted.

For any code you deploy within the cluster you should always use http://gateway.openfaas:8080 as the URL. This will be resolved by the Kubernetes DNS service.

Authentication

OpenFaaS CE and Standard support Basic Authentication, and OpenFaaS for Enterprises supports IAM using OIDC and JSON Web Tokens (JWT).

OpenFaaS CE and Standard

Here's an example of how to list functions using the root user account's password:

export HOST="127.0.0.1:8080"
export PASSWORD=""

curl -s \
    http://admin:$PASSWORD@$HOST/system/functions

OpenFaaS for Enterprises

With OpenFaaS for Enterprises, you can obtain a JWT token for a Kubernetes Service account

How to authenticate to the OpenFaaS API using Kubernetes JWT tokens

Or, you can use the faas-cli to generate a JWT token:

faas-cli pro auth --print-token

# Populate from above
TOKEN=""

curl -s \
    -H "Authorization: Bearer $TOKEN"
    http://$HOST/system/functions

Function authentication

For authentication for functions, see Function Authentication

A note on namespaces

In OpenFaaS For Enterprises, all endpoints other than "list namespaces" support a namespace parameter.

Depending on the endpoint, and operation this is passed either through the body or as a query-string parameter.

GET operations tend to supply the namespace in the query-string, whilst POST and PUT operations tend to supply the namespace in the body.

Example with a GET:

FAAS_DEBUG=1 faas-cli list -n alex
GET http://127.0.0.1:8080/system/functions?namespace=alex

Example with a PUT:

FAAS_DEBUG=1 faas-cli store deploy -n alex figlet
PUT http://127.0.0.1:8080/system/functions
Content-Type: [application/json]
{"service":"figlet","image":"ghcr.io/openfaas/figlet:latest","namespace":"alex","envProcess":"figlet","labels":{},"annotations":{}}

Functions

Invocation

Functions can be invoked by adding the /function/NAME.NAMESPACE path to the gateway URL.

curl -s -i http://127.0.0.1:8080/function/env.openfaas.fn

If no namespace is specified, then the default namespace is used for the installation, this is usually going to be openfaas-fn.

Functions can also be invoked asynchronously by adding the /async-function/NAME.NAMESPACE path to the gateway URL. In this case, a HTTP POST is required with the payload in the body.

If a function is being invoked from within Kubernetes, then the following URL should be used:

http://gateway.openfaas.svc.cluster.local.:8080

Note that in some clusters, the default DNS lookup of "svc.cluster.local" may be different, adapt this as required. The final "." at the end of the line helps to prevent unnecessary DNS lookups.

You can expose Functions with a REST-like mapping or on custom subdomains with the FunctionIngress Custom Resource:

Deploy a function

The minimum valid payload includes the function's name and image, however there are many other fields available.

The function_deployment.go struct from faas-provider provides the full list of fields.

Remember, that FAAS_DEBUG=1 faas-cli store deploy env will print out the HTTP request and response for you to learn from.

FAAS_DEBUG=1 faas-cli store deploy env

PUT http://127.0.0.1:8080/system/functions

Content-Type: [application/json]
User-Agent: [faas-cli/dev]
Authorization: [Basic REDACTED]

{"service":"env","image":"ghcr.io/openfaas/alpine:latest","envProcess":"env","labels":{},"annotations":{}}

Update a function

To update the previously deployed env function with an additional label, run a PUT request with the same payload as before, but with the additional label.

PASSWORD=""

curl -i \
  -X PUT \
   http://admin:$PASSWORD@127.0.0.1:8080/system/functions \
   -H 'Content-Type: application/json' \
  -d '{"service":"env","image":"ghcr.io/openfaas/alpine:latest","envProcess":"env","labels":{"com.openfaas.scale.zero":"true","com.openfaas.scale.zero-duration":"2m"},"annotations":{}}'

Here we've added the label com.openfaas.scale.zero which will instruct the OpenFaaS auto-scaler to scale the function to zero replicas after 2 minutes of inactivity.

Query a function's status

The endpoint to query a function's status returns different data than was inputted via the deploy function endpoint.

Why?

It contains both the deployment data and the status of the function.

PASSWORD=""

curl -s \
  -X GET \
   http://admin:$PASSWORD@127.0.0.1:8080/system/function/env?usage=1 \
   -H 'Content-Type: application/json'

Adding ?usage=1 includes the RAM and CPU usage of the function for commercial editions of OpenFaaS.

Example output:

{
  "name": "env",
  "image": "ghcr.io/openfaas/alpine:latest",
  "namespace": "openfaas-fn",
  "envProcess": "env",
  "labels": {
    "com.openfaas.scale.zero": "true",
    "com.openfaas.scale.zero-duration": "2m"
  },
  "annotations": {},
  "replicas": 1,
  "availableReplicas": 1,
  "createdAt": "2023-07-04T16:17:24Z",
  "usage": {
    "cpu": 0.28076589450860645,
    "totalMemoryBytes": 2367488
  }
}

Note that there is no invocation total on this endpoint, to retrieve that number, you'll need to list all functions.

List all functions

PASSWORD=""

curl -s \
  -X GET \
   http://admin:$PASSWORD@127.0.0.1:8080/system/functions \
   -H 'Content-Type: application/json'

Example response:

{
  {
    "name": "env",
    "image": "ghcr.io/openfaas/alpine:latest",
    "namespace": "openfaas-fn",
    "envProcess": "env",
    "labels": {
      "com.openfaas.scale.zero": "true",
      "com.openfaas.scale.zero-duration": "2m"
    },
    "annotations": {},
    "invocationCount": 46,
    "replicas": 0,
    "availableReplicas": 0,
    "createdAt": "2023-07-04T16:17:24Z"
  }
}

Note that there are 0 replicas (desired) and 0 available replicas (Pods) because the function is scaled to zero due to having been inactive for 2 minutes.

Delete a function

FAAS_DEBUG=1 faas-cli remove env

Deleting: env.
DELETE https://127.0.0.1:8080/system/functions
Content-Type: [application/json]
User-Agent: [faas-cli/dev]
Authorization: [Bearer REDACTED]

{"functionName":"env"}

Secrets

Secrets work in much the same way as functions, however you cannot retrieve the text or binary value of a secret after it has been created for security reasons.

To see the API calls for secrets, run FAAS_DEBUG=1 faas-cli secret create for instance.

POST http://127.0.0.1:8080/system/secrets
Content-Type: [application/json]
{"name":"api-key","namespace":"alex","value":"SECRET"}

List the functions within a namespace:

FAAS_DEBUG=1 faas-cli secret list -n alex
GET http://127.0.0.1:8080/system/secrets?namespace=alex

Logs

Logs are provided in streaming JSON format and come from running Pods.

Therefore if a function is scaled to zero, there will be no logs available. To work around this, you may want to consider an alternative logging provider like Grafana Loki.

You can run FAAS_DEBUG=1 faas-cli logs env to see the API call to query the logs for a function.

FAAS_DEBUG=1 faas-cli logs env --tail --since 1h -o json

GET http://127.0.0.1:8080/system/logs
User-Agent: [faas-cli/dev]
Authorization: [Bearer REDACTED]
follow=true&name=env&since=2023-07-04T16%3A27%3A23%2B01%3A00&tail=-1

Example output when requesting JSON format:

{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:22.223912519Z","text":"2023/07/04 16:32:22 Version: 0.1.4\tSHA: 86e85231a20df03bc9187a31c400f4bbc4e2b9ba\n"}
{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:22.223947899Z","text":"2023/07/04 16:32:22 Timeouts: read: 5s, write: 5s hard: 0s.\n"}
{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:22.223954179Z","text":"2023/07/04 16:32:22 Listening on port: 8080\n"}
{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:22.223983229Z","text":"2023/07/04 16:32:22 Writing lock-file to: /tmp/.lock\n"}
{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:22.223987809Z","text":"2023/07/04 16:32:22 Metrics listening on port: 8081\n"}
{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:23.380573646Z","text":"2023/07/04 16:32:23 Forking fprocess.\n"}
{"name":"env","namespace":"","instance":"env-5b6d68d94c-qqdtj","timestamp":"2023-07-04T16:32:23.382405318Z","text":"2023/07/04 16:32:23 Wrote 932 Bytes - Duration: 0.001823s\n"}

Namespace management

OpenFaaS for Enterprises also includes REST endpoints for listing, creating, deleting and updating namespaces.

Create a namespace with kubectl

To create a namespace and annotate it for OpenFaaS with kubectl, see: Docs: Multiple Namespaces

You can: list, create, update and delete namespaces with the REST API.

Note the difference in URL

The path for listing namespaces (read-only) is /system/namespaces, whilst mutating a single namespace will be either: /system/namespace, or /system/namespaces/NAME.

The field for the body for mutations is name, rather than namespace.

List namespaces

export OPENFAAS_URL="http://127.0.0.1:8080"
export TOKEN=""

curl -s \
  -H "Authorization: Bearer $TOKEN" \
    $OPENFAAS_URL/system/namespaces

Create a namespace

Note that for initial creation, the namespace n1 isn't included in the URL.

export OPENFAAS_URL="http://127.0.0.1:8080"
export TOKEN=""

curl -s \
  -X POST \
  --data-binary '{"name": "n1", "annotations": {"openfaas":"1"}}' \
  -H "Authorization: Bearer $TOKEN" \
    $OPENFAAS_URL/system/namespace/

Note that the trailing / slash in /system/namespace/ is required for this endpoint, and that the name of the namespace must be passed within the body.

Update a namespace

This endpoint can be used to update the annotations for an existing namespace, however the name cannot be changed.

export OPENFAAS_URL="http://127.0.0.1:8080"
export TOKEN=""

curl -s \
  -X PUT \
  --data-binary '{"name": "n1", "annotations": {"openfaas":"1", "customer": "openfaasltd"}}' \
  -H "Authorization: Bearer $TOKEN" \
    $OPENFAAS_URL/system/namespaces/n1

Delete a namespace

export OPENFAAS_URL="http://127.0.0.1:8080"
export TOKEN=""

curl -s \
  -X DELETE
  -H "Authorization: Bearer $TOKEN" \
  --data-binary '{"name": "n1"}' \
    $OPENFAAS_URL/system/namespaces/n1

Only the name of the namespace needs to be included in the body for this endpoint.

Anything else you'd like to know?

Please feel free to reach out if you're a customer using your existing channels or join our weekly community call to talk to us in person.