{"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"api-functions-reference","__idx":0},"children":["API functions reference"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"function-signature","__idx":1},"children":["Function signature"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each API function file must have a single ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["default export"]}," that is a function."," ","Files without a default export, or with a default export that is not callable, are not registered as API endpoints."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The function accepts the following parameters:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["request"]},": a standard Web Handler ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://developer.mozilla.org/en-US/docs/Web/API/Request"},"children":["Request"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context"]},": a custom Redocly ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"#context"},"children":["Context"]}," object"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\nexport default async function (\n  request: Request, \n  context: ApiFunctionsContext\n) {\n  // ...\n}\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Default export required"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Named-only exports such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["export const handler = ..."]}," are skipped during the build."," ","When called in development mode, they produce a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["500"]}," response with a description of the problem."," ","Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["export default function (request, context) { ... }"]}," or re-export a named function as the default with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["export { handler as default }"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"file-system-and-method-routing","__idx":2},"children":["File-system and method routing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To define an API endpoint, use file-system routing."," ","Create API endpoints by adding files inside the designated ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@api"]}," folder."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"define-an-api-endpoint","__idx":3},"children":["Define an API endpoint"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To define an API endpoint for a specific HTTP method, create a file with the following naming convention: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<name>.<method>.ts"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["method"]}," can be a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PUT"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PATCH"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DELETE"]}," HTTP method."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".<method>"]},"part of the filename is optional."," ","If you don't specify the method, the API function is available for all HTTP methods."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the following example, the file ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@api/hello.ts"]}," defines an API endpoint for any HTTP method."," ","To handle a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," request for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/hello"]}," endpoint, create a file ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@api/hello.post.ts"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/hello.post.ts","header":{"title":"@api/hello.post.ts","controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\nexport default async function (request: Request, context: ApiFunctionsContext) {\n  const body = await request.json();\n\n  if (body.name) {\n    // perform operations with the name parameter, for example, send it to the external database or API\n    // ...\n    return context.status(200).json({ message: 'Name saved', name: body.name });\n  } else {\n    return context.status(400).json({ error: 'Missing name' });\n  }\n};\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To define an API endpoint, you can use path parameters with the following naming convention: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/<some>/<path>/[id].<method>.ts"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, if you want to define an API endpoint for a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET"]}," request for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/communities/[id]"]}," endpoint, you can create a file ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@api/communities/[id].get.ts"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/communities/[id].get.ts","header":{"title":"@api/communities/[id].get.ts","controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\nexport default function (request: Request, context: ApiFunctionsContext) {\n  const { id } = context.params;\n  // perform operations with an ID, for example, fetch the community from the external database or API\n  // ...\n  return context.status(200).json({ message: 'Community fetched', id });\n};\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can define a \"catch-all\" API endpoint to match any path inside the folder by following this naming convention: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/<some>/<path>/[...name].<method>.ts"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, the next file ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@api/test/[...other].post.ts"]}," handles a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," request for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/test/anything/you/want"]}," endpoint:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/communities/[...other].post.ts","header":{"title":"@api/communities/[...other].post.ts","controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\nexport default function (request: Request, context: ApiFunctionsContext) {\n  const { other } = context.params; // ['anything', 'you', 'want']\n  // perform operations with other parameters, for example, fetch the community from the external database or API\n  // ...\n  return context.status(200).json({ message: 'Other params', other });\n};\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The response from the example above returns the following JSON:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"message\": \"Other params\",\n  \"other\": [\"anything\", \"you\", \"want\"]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"authorization","__idx":4},"children":["Authorization"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rbac"]}," section of your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly.yaml"]}," file:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","data-title":"redocly.yaml","header":{"title":"redocly.yaml","controls":{"copy":{}}},"source":"rbac:\n  content: \n    '@api/hello.ts': # limit access for the file and corresponding endpoint  (by file path)\n      TeamA: read # TeamA has an access to the /api/hello endpoint\n    '/api/communities/1': # limit access only for the community with id 1 (by url)\n      TeamB: read  # TeamB has an access to the /api/communities/1 endpoint\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"access-environment-variables","__idx":5},"children":["Access environment variables"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To access environment variables, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before using a variable in code, define it for your project."," ","To learn how to use environment variables in API functions, see ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/realm/reunite/project/env-variables#api-functions"},"children":["Use environment variables"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A common use case is authenticating with external systems."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example shows how to fetch a token from an external API using an API key stored in an environment variable:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\n// to define type for process.env, you can use the following code:\ndeclare global {\n  namespace NodeJS {\n    interface ProcessEnv {\n      API_KEY?: string;\n    }\n  }\n  \n  var process: {\n    env: NodeJS.ProcessEnv;\n  };\n}\n\nexport default async function (request: Request, context: ApiFunctionsContext) {\n  const apiKey = process.env.API_KEY; // [!code highlight]\n  // get some token from the external API:\n  try {\n    const response = await fetch(\n      `https://secret-service.com/authentication-tokens`,\n      {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'SERVICE-API-KEY': apiKey\n        }\n      }\n    );\n    // Extract the token from the response\n    const body = await response.json();\n    return context.status(200).json({ message: 'Token fetched', token: body.token });\n  } catch (error) {\n    return context.status(500).json({ error: 'Internal server error' });\n  }\n}\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"debug-code-with-console","__idx":6},"children":["Debug code with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["console"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To log messages to the console inside of an API function, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["console.log | console.error | console.warn | console.info | console.debug | console.trace | console.dir | console.timeEnd | console.table"]}," methods."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"console.log(message: any);\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/simple.post.ts","header":{"title":"@api/simple.post.ts","controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\nexport default async function (request: Request, context: ApiFunctionsContext) {\n  console.log({ user: { name: 'John', age: 30 } });\n  console.log(['javascript', 'typescript', 'python']);\n\n  console.log(request); // logs the Request object\n  console.log(request.method); // logs the method of the Request object\n  console.log(request.url); // logs the URL of the Request object\n  console.log(request.headers); // logs the Headers object\n  console.log(request.headers.get('content-type')); // logs the value of a Content-Type header\n\n  const body = await request.json();\n  console.log(body); // logs the Request body\n\n  console.log(context.params); // logs parsed path parameters\n  console.log(context.query); // logs parsed query parameters\n  console.log(context.cookies); // logs parsed cookies\n  console.log(context.user); // logs user details\n\n  return context.status(200).text('API is working!');\n}\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["a request ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST https://api.acme.com/api/users?type=internal"]}," with the JSON body ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{\"name\": \"David\"}"]}," to the API function outputs the following:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","data-title":"Terminal","header":{"title":"Terminal","controls":{"copy":{}}},"source":"{ user: { name: 'John', age: 30 } }\n[ 'javascript', 'typescript', 'python' ]\nRequest {\n  method: 'POST',\n  url: 'https://api.acme.com/api/users',\n  headers: Headers {\n    accept: '*/*',\n    'accept-encoding': 'gzip, deflate, br',\n    connection: 'keep-alive',\n    'content-length': '16',\n    'content-type': 'application/json',\n    host: 'api.acme.com'\n  },\n  destination: '',\n  referrer: 'about:client',\n  referrerPolicy: '',\n  mode: 'cors',\n  credentials: 'same-origin',\n  cache: 'default',\n  redirect: 'follow',\n  integrity: '',\n  keepalive: false,\n  isReloadNavigation: false,\n  isHistoryNavigation: false,\n  signal: AbortSignal { aborted: false }\n}\nPOST\nhttps://api.acme.com/api/users\nHeaders {\n  accept: '*/*',\n  'accept-encoding': 'gzip, deflate, br',\n  connection: 'keep-alive',\n  'content-length': '16',\n  'content-type': 'application/json',\n  host: 'api.acme.com'\n}\napplication/json\n{ name: 'David' }\n{}\n{}\n{}\n{ teams: [ 'anonymous' ], claims: {}, isAuthenticated: false }\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"context","__idx":7},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"properties","__idx":8},"children":["Properties"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"width":"35%","data-label":"Property"},"children":["Property "]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.user.email"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The user's email address."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.user.teams"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["[string]"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The list of teams the user belongs to."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["[\"teamA\", \"teamB\"]"]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.user.claims"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Parsed claims from the identity provider (IdP)."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{ email: string; authCookie: string }"]},"."]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.user.idpAccessToken"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The raw access token issued by the IdP."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.user.idpIdToken"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The raw ID token issued by the IdP."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.config"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["object"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your project's configuration file (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly.yaml"]}," by default)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.params"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Path parameters from the request, or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{}"]}," if none exist."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, for path ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/users/[userId]/projects/[projectId]"]}," the params are: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{ userId: \"123\", projectId: \"1\" }"]},"."]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.query"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Request query parameters, or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{}"]}," if none exist."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, for path ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/users?active=true"]},", the query is: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{ active: \"true\" }"]},"."]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.cookies"]}]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Cookies sent with the request, or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{}"]}," if none are present."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{ authToken: \"secretToken\" }"]},"."]}]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"context-methods","__idx":9},"children":["Context methods"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The context object includes the following methods for sending a standard Web Handler ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://developer.mozilla.org/en-US/docs/Web/API/Response"},"children":["Response"]},":"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"contextdeletecookie","__idx":10},"children":["context.deleteCookie"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"context.deleteCookie(name: string) => ApiFunctionsContext\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Deletes a cookie by name."," ","Returns the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context"]}," object for chaining."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"contextjson","__idx":11},"children":["context.json"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"context.json(body: object) => Response\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Sends a response body serialized as ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON"},"children":["JSON"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"contextredirect","__idx":12},"children":["context.redirect"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"context.redirect(url: string, code?: number) => Response\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Redirects to the specified URL."," ","Defaults to a 302 status code unless otherwise specified."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"contextsetcookie","__idx":13},"children":["context.setCookie"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"context.setCookie(name: string, value: string, options?: CookieOptions) => ApiFunctionsContext\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Sets a cookie on the response."," ","Returns the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context"]}," object for chaining."," ","Available ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["options"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["domain"]}," - string"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["expires"]}," - date"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["httpOnly"]}," - boolean"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["maxAge"]}," - number"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["path"]}," - string"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secure"]}," - boolean"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signed"]}," - boolean"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sameSite"]}," - ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Strict"]}," | ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Lax"]}," | ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["None"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"contextstatus","__idx":14},"children":["context.status"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"context.status(code: number) => ApiFunctionsContext\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Sets the HTTP status code for the response."," ","Returns the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context"]}," object to allow chaining."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context.status(200).json({ tickets: 1 })"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"contexttext","__idx":15},"children":["context.text"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"context.text(body: string) => Response\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Sends a plain text response body."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"change-api-functions-location","__idx":16},"children":["Change API functions location"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["By default, API functions are located in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@api"]}," folder."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To customize the location, add an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apiFunctions"]}," section to your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly.yaml"]}," file at the root of your project."," ","To learn how to configure API functions in your project, see: ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/realm/config/api-functions"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apiFunctions"]}]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","data-title":"redocly.yaml","header":{"title":"redocly.yaml","controls":{"copy":{}}},"source":"apiFunctions:\n  folders:\n    - /my/api/folder/path/\n    - /my/second/api/folder/path/\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This configuration means that API functions are located in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/my/api/folder/path/"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/my/second/api/folder/path/"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/@api/"]},"."," ","Endpoints from these folders are available at ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/my/api/folder/path/..."]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/my/second/api/folder/path/..."]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/..."]},", respectively."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"limitations","__idx":17},"children":["Limitations"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["API functions have the following limits:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Limitation"},"children":["Limitation"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Maximum value"},"children":["Maximum value"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Execution timeout"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["10 seconds"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["API functions must complete within 10 seconds."," ","Otherwise, the function terminates and returns a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["504 Gateway Timeout"]}," error."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Memory usage"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["500MB"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["API functions are limited to 500MB of memory."," ","If exceeded, the function is terminated with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["502 Internal Server Error"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Request size"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["5MB"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The maximum size of the request body is 5MB."," ","The maximum allowed request body size is 5MB."," ","Larger requests are rejected with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["413 Payload Too Large"]}," error."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Response size"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["5MB"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The maximum allowed response body size is 5MB."," ","Larger responses are rejected with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["500 Internal Server Error"]},"."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["These limitations ensure consistent performance and protect the system from resource overuse."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"api-functions-examples","__idx":18},"children":["API functions examples"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can return either a native ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Response"]}," object or use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["context"]}," helper methods — both approaches work the same."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"simple-function-without-arguments","__idx":19},"children":["Simple function without arguments"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/simple.ts","header":{"title":"@api/simple.ts","controls":{"copy":{}}},"source":"export default function () {\n  // When no arguments are used, you can still return a Response object\n  // This example returns a 200 OK status with a text body\n  return new Response('API is working!', {\n    status: 200,\n    headers: {\n      'Content-Type': 'text/plain'\n    }\n  });\n}\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"function-that-uses-request-only","__idx":20},"children":["Function that uses request only"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/echo-body.ts","header":{"title":"@api/echo-body.ts","controls":{"copy":{}}},"source":"export default async function (request: Request) {\n  // Only process POST, PUT, PATCH requests with body content\n  if (['POST', 'PUT', 'PATCH'].includes(request.method)) {\n    try {\n      // Extract JSON body from request\n      const body = await request.json();\n      \n      // Return the body content as the response\n      return new Response(JSON.stringify({\n        success: true,\n        message: 'Received your data',\n        data: body\n      }), {\n        status: 200,\n        headers: {\n          'Content-Type': 'application/json'\n        }\n      });\n    } catch (error) {\n      // Handle JSON parsing errors\n      return new Response(JSON.stringify({\n        success: false,\n        message: 'Invalid JSON in request body'\n      }), {\n        status: 400,\n        headers: {\n          'Content-Type': 'application/json'\n        }\n      });\n    }\n  }\n  \n  // Return method not allowed for non-supported methods\n  return new Response(JSON.stringify({\n    success: false,\n    message: 'Method not supported, use POST, PUT or PATCH'\n  }), {\n    status: 405,\n    headers: {\n      'Content-Type': 'application/json',\n      'Allow': 'POST, PUT, PATCH'\n    }\n  });\n}\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"function-that-uses-context","__idx":21},"children":["Function that uses context"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","data-title":"@api/hello.ts","header":{"title":"@api/hello.ts","controls":{"copy":{}}},"source":"import type { ApiFunctionsContext } from '@redocly/config';\n\nexport default async function (request: Request, context: ApiFunctionsContext) {\n  if (context.cookies) {\n    // Do something with the cookies like checking if the user is logged in\n    // ...\n\n    // If the user is not logged in, redirect to the login page\n    return context.redirect('/login');\n  }\n  \n  // Access user information if available\n  if (context.user) {\n    const userEmail = context.user.email;\n    const userTeams = context.user.teams;\n    // Additional logic using identity information\n    // ...\n  }\n\n  // Handle the request as needed\n  return context.status(200).json({ message: 'Hello World' });\n};\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"resources","__idx":22},"children":["Resources"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/realm/customization/api-functions/create-api-functions"},"children":["API functions tutorial: render weather data in a Markdoc tag"]}]}," - End-to-end tutorial that builds an API function and a custom Markdoc tag"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/realm/reunite/project/test-api-functions"},"children":["Test API functions"]}]}," - Send requests to your API functions with Replay in the Reunite editor"]}]}]},"frontmatter":{"products":["Realm","Reef"],"plans":["Pro","Enterprise","Enterprise+"]},"tagList":["admonition","table"],"title":"API functions reference","lastModified":"2026-10-01T23:00:57.000Z"}