Skip to main content
Version: 10.x

API Handler

tRPC is not a backend of its own, but rather lives inside of other backends such as Next.js or Express. Despite that, most of tRPC's features and syntax are the same no matter which backend you are using. The API handler, also called adapter, enables this by acting as the glue between HTTP requests to your backend and tRPC.

The API Handler sits on a route in your server (usually /api/trpc, but this is just a convention) and processes all requests to that route and its subroutes. It receives a request from the server, uses the createContext function to generate context, and then sends the request and context to a procedure in the router.

It can also take some optional arguments such as onError, a callback function that runs whenever an error is thrown inside of a procedure.

Below is an example implementation in Next.js. The process is similar for AWS Lambda, Express, Fastify, and the Fetch API.

Next.js example

pages/api/trpc/[trpc].ts
ts
import { createNextApiHandler } from '@trpc/server/adapters/next';
import { createContext } from '../../../server/trpc/context';
import { appRouter } from '../../../server/trpc/router/_app';
// export API handler
export default createNextApiHandler({
router: appRouter, // your outermost router, see https://trpc.io/docs/procedures
createContext, // your request context, see https://trpc.io/docs/context
});
pages/api/trpc/[trpc].ts
ts
import { createNextApiHandler } from '@trpc/server/adapters/next';
import { createContext } from '../../../server/trpc/context';
import { appRouter } from '../../../server/trpc/router/_app';
// export API handler
export default createNextApiHandler({
router: appRouter, // your outermost router, see https://trpc.io/docs/procedures
createContext, // your request context, see https://trpc.io/docs/context
});

Advanced Usage

While you can usually just "set and forget" the API Handler as shown above, sometimes you might want to modify it further.

The API handler that is created by createNextApiHandler and equivalents in other frameworks is just a function that takes req and res objects. This means you can also modify those objects before passing them to the handler, for example to enable CORS.

pages/api/trpc/[trpc].ts
ts
import { createNextApiHandler } from '@trpc/server/adapters/next';
import { createContext } from '../../../server/trpc/context';
import { appRouter } from '../../../server/trpc/router/_app';
// create the API handler, but don't return it yet
const nextApiHandler = createNextApiHandler({
router: appRouter,
createContext,
});
// @see https://nextjs.org/docs/api-routes/introduction
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
// Modify `req` and `res` objects here
// In this case, we are enabling CORS
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') {
res.writeHead(200);
return res.end();
}
// pass the (modified) req/res to the handler
return nextApiHandler(req, res);
}
pages/api/trpc/[trpc].ts
ts
import { createNextApiHandler } from '@trpc/server/adapters/next';
import { createContext } from '../../../server/trpc/context';
import { appRouter } from '../../../server/trpc/router/_app';
// create the API handler, but don't return it yet
const nextApiHandler = createNextApiHandler({
router: appRouter,
createContext,
});
// @see https://nextjs.org/docs/api-routes/introduction
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
// Modify `req` and `res` objects here
// In this case, we are enabling CORS
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') {
res.writeHead(200);
return res.end();
}
// pass the (modified) req/res to the handler
return nextApiHandler(req, res);
}