Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Langfuse Langfuse CreateAuthedProjectAPIRoute

From Leeroopedia
Knowledge Sources
Domains API Security, Trace Ingestion
Last Updated 2026-02-14 00:00 GMT

Overview

Concrete tool for wrapping Next.js API route handlers with authentication, rate limiting, schema validation, and OpenTelemetry context propagation provided by Langfuse.

Description

createAuthedProjectAPIRoute is a higher-order function that accepts a RouteConfig object describing an API endpoint and returns a fully instrumented Next.js API handler. The returned handler performs the following steps in order:

  1. Authentication: Calls verifyAuth which attempts admin API key authentication (if allowed) followed by Basic Auth. Basic Auth decodes the Authorization: Basic base64(publicKey:secretKey) header and verifies the key pair via ApiAuthService, which queries the database with Redis caching. Admin API key authentication uses crypto.timingSafeEqual for constant-time comparison of the key against the ADMIN_API_KEY environment variable. Admin auth requires the key in both the Bearer token and the x-langfuse-admin-api-key header for defense-in-depth.
  1. Rate Limiting: The authenticated scope is passed to RateLimitService.rateLimitRequest along with the configured rate limit resource (defaulting to "public-api"). If the request exceeds the rate limit, a 429 response is returned with appropriate headers.
  1. Schema Validation: If querySchema is provided, req.query is parsed through it. If bodySchema is provided, req.body is parsed through it. Failed parsing throws a Zod validation error.
  1. OpenTelemetry Context: An OpenTelemetry context is created with the project ID and request headers, and the handler function is executed within this context via opentelemetry.context.with.
  1. Response Validation (dev only): In development mode, the handler's return value is validated against responseSchema. Failures are logged but do not affect the response.
  1. Response: The handler's return value is serialized as JSON and sent with the configured success status code (default 200).

Usage

Use this function when creating any new public API endpoint that requires project-scoped authentication. It is the standard pattern for all routes under /web/src/pages/api/public/.

Code Reference

Source Location

  • Repository: langfuse
  • File: web/src/features/public-api/server/createAuthedProjectAPIRoute.ts
  • Lines: L234-319

Signature

export const createAuthedProjectAPIRoute = <
  TQuery extends ZodType<any>,
  TBody extends ZodType<any>,
  TResponse extends ZodType<any>,
>(
  routeConfig: RouteConfig<TQuery, TBody, TResponse>,
): ((req: NextApiRequest, res: NextApiResponse) => Promise<void>)

Import

import { createAuthedProjectAPIRoute } from "@/src/features/public-api/server/createAuthedProjectAPIRoute";

I/O Contract

Inputs

Name Type Required Description
routeConfig.name string Yes Endpoint name used for logging and metrics.
routeConfig.querySchema ZodType<any> No Zod schema for validating req.query. If omitted, query is treated as an empty object.
routeConfig.bodySchema ZodType<any> No Zod schema for validating req.body. If omitted, body is treated as an empty object.
routeConfig.responseSchema ZodType<any> Yes Zod schema for the response shape. Validated in development mode only.
routeConfig.successStatusCode number No HTTP status code for successful responses. Defaults to 200.
routeConfig.rateLimitResource RateLimitResource No Rate limit bucket identifier. Defaults to "public-api".
routeConfig.isAdminApiKeyAuthAllowed boolean No Whether to allow ADMIN_API_KEY Bearer token authentication. Defaults to false. Only works on self-hosted instances.
routeConfig.fn (params) => Promise<TResponse> Yes The handler function that receives validated query, body, request, response, and auth scope.

Outputs

Name Type Description
(return value) (req: NextApiRequest, res: NextApiResponse) => Promise<void> A Next.js API handler function that performs auth, rate limiting, validation, and calls the provided handler.
auth.scope.projectId string The authenticated project's ID, available inside the handler via auth.scope.projectId.
auth.scope.accessLevel "project" Always "project" for routes created with this function.
auth.scope.orgId string The organization ID associated with the authenticated API key.
auth.scope.plan string The billing plan of the organization (e.g., "oss", "cloud:pro").

Usage Examples

Basic Authenticated Endpoint

import { createAuthedProjectAPIRoute } from "@/src/features/public-api/server/createAuthedProjectAPIRoute";
import { z } from "zod/v4";

const handler = createAuthedProjectAPIRoute({
  name: "get-traces",
  querySchema: z.object({
    page: z.coerce.number().int().min(1).default(1),
    limit: z.coerce.number().int().min(1).max(100).default(50),
  }),
  responseSchema: z.object({
    data: z.array(z.object({ id: z.string(), name: z.string().nullish() })),
    meta: z.object({ totalItems: z.number(), page: z.number() }),
  }),
  fn: async ({ query, auth }) => {
    const traces = await getTraces({
      projectId: auth.scope.projectId,
      page: query.page,
      limit: query.limit,
    });
    return traces;
  },
});

export default handler;

Ingestion Endpoint with Custom Rate Limit

import { createAuthedProjectAPIRoute } from "@/src/features/public-api/server/createAuthedProjectAPIRoute";
import { z } from "zod/v4";

const handler = createAuthedProjectAPIRoute({
  name: "ingest-events",
  rateLimitResource: "ingestion",
  bodySchema: z.object({
    batch: z.array(z.unknown()),
  }),
  responseSchema: z.object({
    successes: z.array(z.object({ id: z.string(), status: z.number() })),
    errors: z.array(z.object({ id: z.string(), status: z.number(), error: z.string().optional() })),
  }),
  successStatusCode: 207,
  fn: async ({ body, auth }) => {
    return await processEventBatch(body.batch, auth);
  },
});

export default handler;

Admin API Key Endpoint (Self-Hosted)

import { createAuthedProjectAPIRoute } from "@/src/features/public-api/server/createAuthedProjectAPIRoute";
import { z } from "zod/v4";

const handler = createAuthedProjectAPIRoute({
  name: "admin-project-config",
  isAdminApiKeyAuthAllowed: true,
  responseSchema: z.object({ config: z.record(z.string(), z.unknown()) }),
  fn: async ({ auth }) => {
    // auth.scope.projectId comes from x-langfuse-project-id header for admin auth
    const config = await getProjectConfig(auth.scope.projectId);
    return { config };
  },
});

export default handler;

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment