Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

tRPC Integration

This guide shows how to integrate tRPC with oRPC, so you can use oRPC features in your existing tRPC applications.

Installation

npm install @orpc/trpc@beta
pnpm add @orpc/trpc@beta
yarn add @orpc/trpc@beta
bun add @orpc/trpc@beta

Router Conversion

toORPCRouter converts a tRPC router into an oRPC router:

import { toORPCRouter } from '@orpc/trpc'

const orpcRouter = toORPCRouter(trpcRouter)

The result is a regular oRPC router that works with any oRPC feature. For example, you can expose it through an RPC Handler or OpenAPI Handler, or call it directly with Server-Side Clients.

Error Formatting

toORPCRouter does not support tRPC Error Formatting. Instead, errors thrown by tRPC are wrapped in ORPCError.

const handler = new OpenAPIHandler(orpcRouter, {
  interceptors: [
    async ({ next }) => {
      try {
        return await next()
      }
      catch (error) {
        if (
          error instanceof ORPCError
          && error.cause instanceof TRPCError
          && error.cause.cause instanceof z.ZodError
        ) {
          throw new ORPCError('UNPROCESSABLE_CONTENT', {
            message: z.prettifyError(error.cause.cause),
            data: z.flattenError(error.cause.cause),
            cause: error.cause.cause,
          })
        }

        throw error
      }
    },
  ],
})

Metadata

toTRPCMeta bridges oRPC metadata with tRPC meta. It returns a plain object that you can pass to tRPC .meta calls.

import { openapi } from '@orpc/openapi'
import { toTRPCMeta } from '@orpc/trpc'

export const t = initTRPC.context<Context>().create()

const example = t.procedure
  .meta(toTRPCMeta(openapi({ path: '/hello', summary: 'Hello procedure' }))) 
  .input(z.object({ name: z.string() }))
  .query(({ input }) => {
    return `Hello, ${input.name}!`
  })

const merged = t.procedure
  .meta({
    ...toTRPCMeta( 
      openapi({ path: '/hello' }), 
      openapi({ method: 'POST' }), 
    ), 
    other: 'value',
  })
  .input(z.object({ name: z.string() }))
  .mutation(({ input }) => {
    return `Hello, ${input.name}!`
  })

Last updated on August 6, 2026

Was this page helpful?