Last updated

API functions reference

Use API functions to add dynamic data fetching and server-side logic to your project. Integrate with external systems, manipulate data, and enhance your Redocly projects with dynamic content.

Function signature

The function accepts the following parameters:

  • request: a standard Web Handler Request
  • context: a custom Redocly Context object
import type { ApiFunctionsContext } from '@redocly/config';

export default async function (
  request: Request, 
  context: ApiFunctionsContext
) {
  // ...
}

File-system and method routing

To define an API endpoint, use file-system routing. API endpoints are created by adding files inside the designated @api folder.

Change API functions location

By default, API functions are located in the @api folder.

To customize the location, add an apiFunctions section to your redocly.yaml file at the root of your project. Learn more about configuring apiFunctions.

For example:

redocly.yaml
apiFunctions:
  folders:
    - /my/api/folder/path/
    - /my/second/api/folder/path/

This configuration means that API functions are located in /my/api/folder/path/, /my/second/api/folder/path/ and /@api/. Endpoints from these folders are available at /my/api/folder/path/..., /my/second/api/folder/path/..., and /api/..., respectively.

Define an API endpoint

To define an API endpoint for a specific HTTP method, create a file with the following naming convention: <name>.<method>.ts.

method can be a GET, POST, PUT, PATCH or DELETE HTTP method.

The .<method>part of the filename is optional. If you don't specify the method, the API function is available for all HTTP methods.

In the following example, the file @api/hello.ts defines an API endpoint for any HTTP method. To handle a POST request for the /api/hello endpoint, create a file @api/hello.post.ts.

@api/hello.post.ts
import type { ApiFunctionsContext } from '@redocly/config';

export default async function (request: Request, context: ApiFunctionsContext) {
  const body = await request.json();

  if (body.name) {
    // perform operations with the name parameter, for example, send it to the external database or API
    // ...
    return context.status(200).json({ message: 'Name saved', name: body.name });
  } else {
    return context.status(400).json({ error: 'Missing name' });
  }
};

To define an API endpoint, you can use path parameters with the following naming convention: /<some>/<path>/[id].<method>.ts.

For example, if you want to define an API endpoint for a GET request for the /api/communities/[id] endpoint, you can create a file @api/communities/[id].get.ts:

@api/communities/[id].get.ts
import type { ApiFunctionsContext } from '@redocly/config';

export default function (request: Request, context: ApiFunctionsContext) {
  const { id } = context.params;
  // perform operations with an ID, for example, fetch the community from the external database or API
  // ...
  return context.status(200).json({ message: 'Community fetched', id });
};

You can define a "catch-all" API endpoint to match any path inside the folder by following this naming convention: /<some>/<path>/[...name].<method>.ts.

For example, the next file @api/test/[...other].post.ts handles a POST request for the /api/test/anything/you/want endpoint:

@api/communities/[...other].post.ts
import type { ApiFunctionsContext } from '@redocly/config';

export default function (request: Request, context: ApiFunctionsContext) {
  const { other } = context.params; // ['anything', 'you', 'want']
  // perform operations with other parameters, for example, fetch the community from the external database or API
  // ...
  return context.status(200).json({ message: 'Other params', other });
};

The response from the example above returns the following JSON:

{
  "message": "Other params",
  "other": ["anything", "you", "want"]
}

Authorization

API functions follow the same RBAC rules as other Redocly resources, based on user roles and teams. To grant access to an API function, add its file path or endpoint to the rbac section of your redocly.yaml file:

redocly.yaml
rbac:
  content: 
    '@api/hello.ts': # limit access for the file and corresponding endpoint  (by file path)
      TeamA: read # TeamA has an access to the /api/hello endpoint
    '/api/communities/1': # limit access only for the community with id 1 (by url)
      TeamB: read  # TeamB has an access to the /api/communities/1 endpoint

Access environment variables

To access environment variables, use the process.env.VAR_NAME syntax. This lets you securely work with API keys, secrets, and other values you don’t want exposed in client-facing code.

A common use case is authenticating with external systems.

The following example shows how to fetch a token from an external API using an API key stored in an environment variable:

import type { ApiFunctionsContext } from '@redocly/config';

export default async function (request: Request, context: ApiFunctionsContext) {
  const apiKey = process.env.API_KEY; 
  // get some token from the external API:
  try {
    const response = await fetch(
      `https://secret-service.com/authentication-tokens`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'SERVICE-API-KEY': apiKey
        }
      }
    );
    // Extract the token from the response
    const body = await response.json();
    return context.status(200).json({ message: 'Token fetched', token: body.token });
  } catch (error) {
    return context.status(500).json({ error: 'Internal server error' });
  }
}

context

The context object provides additional information and helper methods for API functions. It includes user details, project configuration, and utilities for accessing request data and sending responses.

Properties

Property TypeDescription
context.user.emailstringThe user's email address.

context.user.teams

[string]

The list of teams the user belongs to.

For example: ["teamA", "teamB"]

context.user.claims

object

Parsed claims from the identity provider (IdP).

For example: { email: string; authCookie: string }.

context.user.idpAccessTokenstringThe raw access token issued by the IdP.
context.user.idpIdTokenstringThe raw ID token issued by the IdP.
context.configobjectYour project's configuration file (redocly.yaml by default).

context.query

object

Request query parameters, or {} if none exist.

For example, for path /users?active=true, the query is: { active: "true" }.

context.cookies

object

Cookies sent with the request, or {} if none are present.

For example, { authToken: "secretToken" }.

context.params

object

Path parameters from the request, or {} if none exist.

For example, for path /users/[userId]/projects/[projectId] the params are: { userId: "123", projectId: "1" }.

context.headersobjectHeaders sent with the request, or {} if none are present.
  {
     host: "localhost:3000",
     'Content-Type': "application/json"
     connection: "keep-alive",
     'accept-language': "en-US,en;q=0.5",
  }

Context methods

The context object includes the following methods for sending a standard Web Handler Response:

context.deleteCookie

context.deleteCookie(name: string) => ApiFunctionsContext

Deletes a cookie by name. Returns the context object for chaining.

context.json

context.json(body: object) => Response

Sends a response body serialized as JSON.

context.redirect

context.redirect(url: string, code?: number) => Response

Redirects to the specified URL. Defaults to a 302 status code unless otherwise specified.

context.setCookie

context.setCookie(name: string, value: string, options?: CookieOptions) => ApiFunctionsContext

Sets a cookie on the response. Returns the context object for chaining. Available options:

  • domain - string
  • expires - date
  • httpOnly - boolean
  • maxAge - number
  • path - string
  • secure - boolean
  • signed - boolean
  • sameSite - Strict | Lax | None

context.status

context.status(code: number) => ApiFunctionsContext

Sets the HTTP status code for the response. Returns the context object to allow chaining.

For example: context.status(200).json({ tickets: 1 }).

context.text

context.text(body: string) => Response

Sends a plain text response body.

Limitations

API functions have the following limits:

LimitationMaximum valueDescription
Execution timeout10 secondsAPI functions must complete within 10 seconds. Otherwise, the function terminates and returns a 504 Gateway Timeout error.
Memory usage500MBAPI functions are limited to 500MB of memory. If exceeded, the function is terminated with a 502 Internal Server Error.
Request size5MBThe maximum size of the request body is 5MB. The maximum allowed request body size is 5MB. Larger requests are rejected with a 413 Payload Too Large error.
Response size5MBThe maximum allowed response body size is 5MB. Larger responses are rejected with a 500 Internal Server Error.

These limitations ensure consistent performance and protect the system from resource overuse.

API functions examples

You can return either a native Response object or use context helper methods — both approaches work the same.

Simple function without arguments

@api/simple.ts
export default function () {
  // When no arguments are used, you can still return a Response object
  // This example returns a 200 OK status with a text body
  return new Response('API is working!', {
    status: 200,
    headers: {
      'Content-Type': 'text/plain'
    }
  });
}

Function that uses request only

@api/echo-body.ts
export default async function (request: Request) {
  // Only process POST, PUT, PATCH requests with body content
  if (['POST', 'PUT', 'PATCH'].includes(request.method)) {
    try {
      // Extract JSON body from request
      const body = await request.json();
      
      // Return the body content as the response
      return new Response(JSON.stringify({
        success: true,
        message: 'Received your data',
        data: body
      }), {
        status: 200,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    } catch (error) {
      // Handle JSON parsing errors
      return new Response(JSON.stringify({
        success: false,
        message: 'Invalid JSON in request body'
      }), {
        status: 400,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }
  }
  
  // Return method not allowed for non-supported methods
  return new Response(JSON.stringify({
    success: false,
    message: 'Method not supported, use POST, PUT or PATCH'
  }), {
    status: 405,
    headers: {
      'Content-Type': 'application/json',
      'Allow': 'POST, PUT, PATCH'
    }
  });
}

Function that uses context

@api/hello.ts
import type { ApiFunctionsContext } from '@redocly/config';

export default async function (request: Request, context: ApiFunctionsContext) {
  if (context.cookies) {
    // Do something with the cookies like checking if the user is logged in
    // ...

    // If the user is not logged in, redirect to the login page
    return context.redirect('/login');
  }
  
  // Access user information if available
  if (context.user) {
    const userEmail = context.user.email;
    const userTeams = context.user.teams;
    // Additional logic using identity information
    // ...
  }

  // Handle the request as needed
  return context.status(200).json({ message: 'Hello World' });
};

Resources