Skip to content

Getting Started

oRPC (OpenAPI Remote Procedure Call) combines RPC (Remote Procedure Call) with OpenAPI, allowing you to define and call remote (or local) procedures through a type-safe API while adhering to the OpenAPI specification.

oRPC simplifies RPC service definition, making it easy to build scalable applications—from simple scripts to complex microservices.

This guide covers the basics: defining procedures, handling errors, and integrating with popular frameworks.

Prerequisites

  • Node.js 18+ (20+ recommended) | Bun | Deno | Cloudflare Workers
  • A package manager: npm | pnpm | yarn | bun | deno
  • A TypeScript project (strict mode recommended)

Installation

sh
npm install @orpc/server@latest @orpc/client@latest
sh
yarn add @orpc/server@latest @orpc/client@latest
sh
pnpm add @orpc/server@latest @orpc/client@latest
sh
bun add @orpc/server@latest @orpc/client@latest
sh
deno install npm:@orpc/server@latest npm:@orpc/client@latest

Define App Router

We'll use Zod for schema validation (optional, any standard schema is supported).

ts
import type { IncomingHttpHeaders } from 'node:http'
import { 
ORPCError
,
os
} from '@orpc/server'
import {
z
} from 'zod'
const
PlanetSchema
=
z
.
object
({
id
:
z
.
number
().
int
().
min
(1),
name
:
z
.
string
(),
description
:
z
.
string
().
optional
(),
}) export const
listPlanet
=
os
.
input
(
z
.
object
({
limit
:
z
.
number
().
int
().
min
(1).
max
(100).
optional
(),
cursor
:
z
.
number
().
int
().
min
(0).
default
(0),
}), ) .
handler
(async ({
input
}) => {
// your list code here return [{
id
: 1,
name
: 'name' }]
}) export const
findPlanet
=
os
.
input
(
PlanetSchema
.
pick
({
id
: true }))
.
handler
(async ({
input
}) => {
// your find code here return {
id
: 1,
name
: 'name' }
}) export const
createPlanet
=
os
.
$context
<{
headers
: IncomingHttpHeaders }>()
.
use
(({
context
,
next
}) => {
const
user
=
parseJWT
(
context
.
headers
.
authorization
?.
split
(' ')[1])
if (
user
) {
return
next
({
context
: {
user
} })
} throw new
ORPCError
('UNAUTHORIZED')
}) .
input
(
PlanetSchema
.
omit
({
id
: true }))
.
handler
(async ({
input
,
context
}) => {
// your create code here return {
id
: 1,
name
: 'name' }
}) export const
router
= {
planet
: {
list
:
listPlanet
,
find
:
findPlanet
,
create
:
createPlanet
} }

Create Server

Using Node.js as the server runtime, but oRPC also supports other runtimes like Bun, Deno, Cloudflare Workers, ...

ts
import { 
createServer
} from 'node:http'
import {
RPCHandler
} from '@orpc/server/node'
import {
CORSPlugin
} from '@orpc/server/plugins'
const
handler
= new
RPCHandler
(
router
, {
plugins
: [new
CORSPlugin
()]
}) const
server
=
createServer
(async (
req
,
res
) => {
const
result
= await
handler
.
handle
(
req
,
res
, {
context
: {
headers
:
req
.
headers
}
}) if (!
result
.
matched
) {
res
.
statusCode
= 404
res
.
end
('No procedure matched')
} })
server
.
listen
(
3000, '127.0.0.1', () =>
console
.
log
('Listening on 127.0.0.1:3000')
)

Learn more about RPCHandler.

Create Client

ts
import type { 
RouterClient
} from '@orpc/server'
import {
createORPCClient
} from '@orpc/client'
import {
RPCLink
} from '@orpc/client/fetch'
const
link
= new
RPCLink
({
url
: 'http://127.0.0.1:3000',
headers
: {
Authorization
: 'Bearer token' },
}) export const
orpc
:
RouterClient
<typeof
router
> =
createORPCClient
(
link
)

Supports both client-side clients and server-side clients.

Call Procedure

End-to-end type-safety and auto-completion out of the box.

ts
const 
planet
= await
orpc
.
planet
.
find
({
id
: 1 })
orpc
.
planet
.
create

Next Steps

This guide introduced the RPC aspects of oRPC. To explore OpenAPI integration, visit the OpenAPI Guide.

Released under the MIT License.