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 add 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 * as
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, etc.

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.