Methods <-> Type mapping
HTTP Method
Mapping
Notes
GET
.query()
Input JSON-stringified in query param.
e.g. myQuery?input=${encodeURIComponent(JSON.stringify(input))}
POST
.mutation()
Input as POST body.
GET
.subscription()
Subscriptions are supported via Server-sent Events using httpSubscriptionLink, or via WebSockets using wsLink.
Accessing nested procedures
Nested procedures are separated by dots, so a request to byId below would end up being a request to /api/trpc/post.byId.
ts
export const appRouter = router({
post: router({
`byId: publicProcedure.input(String).query(async (opts) => {`
`// [...]`
`}),`
}),
});
Batching
When batching, we combine all parallel procedure calls of the same HTTP method in one request using a data loader.
- The called procedures' names are combined by a comma (
,) in thepathname - Input parameters are sent as a query parameter called
inputwhich has the shapeRecord<number, unknown>. - We also need to pass
batch=1as a query parameter. - If the response has different statuses, we send back
207 Multi-Status(e.g., if one call errored and one succeeded)
Batching Example Request
Given a router like this exposed at /api/trpc:
server/router.ts
tsx
export const appRouter = t.router({
postById: t.procedure.input(String).query(async (opts) => {
`const post = await opts.ctx.post.findUnique({`
`where: { id: opts.input },`
`});`
`return post;`
}),
relatedPosts: t.procedure.input(String).query(async (opts) => {
`const posts = await opts.ctx.findRelatedPostsById(opts.input);`
`return posts;`
}),
});
... And two queries defined like this in a React component:
MyComponent.tsx
tsx
export function MyComponent() {
const post1 = trpc.postById.useQuery('1');
const relatedPosts = trpc.relatedPosts.useQuery('1');
return (
`<pre>`
`{JSON.stringify(`
`{`
`post1: post1.data ?? null,`
`relatedPosts: relatedPosts.data ?? null,`
`},`
`null,`
`4,`
`)}`
`</pre>`
);
}
The above would result in exactly 1 HTTP call with this data:
Location property
Value
pathname
/api/trpc/postById,relatedPosts
search
?batch=1&input=%7B%220%22%3A%221%22%2C%221%22%3A%221%22%7D *
*) input in the above is the result of:
ts
encodeURIComponent(
JSON.stringify({
`` 0: '1', // <-- input for `postById` ``
`` 1: '1', // <-- input for `relatedPosts` ``
}),
);
Batching Example Response
Example output from server
HTTP Response Specification
In order to have a specification that works regardless of the transport layer we try to conform to JSON-RPC 2.0 where possible.
Successful Response
Example JSON Response
ts
interface SuccessResponse {
result: {
`data: TOutput; // output from procedure`
}
}
Error Response
Example JSON Response
- When possible, we propagate HTTP status codes from the error thrown.
- If the response has different statuses, we send back
207 Multi-Status(e.g., if one call errored and one succeeded) - For more on errors and how to customize them see Error Formatting.
Error Codes <-> HTTP Status
ts
const HTTP_STATUS_CODES = {
PARSE_ERROR: 400,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
PAYMENT_REQUIRED: 402,
FORBIDDEN: 403,
NOT_FOUND: 404,
METHOD_NOT_SUPPORTED: 405,
TIMEOUT: 408,
CONFLICT: 409,
PRECONDITION_FAILED: 412,
PAYLOAD_TOO_LARGE: 413,
UNSUPPORTED_MEDIA_TYPE: 415,
UNPROCESSABLE_CONTENT: 422,
PRECONDITION_REQUIRED: 428,
TOO_MANY_REQUESTS: 429,
CLIENT_CLOSED_REQUEST: 499,
INTERNAL_SERVER_ERROR: 500,
NOT_IMPLEMENTED: 501,
BAD_GATEWAY: 502,
SERVICE_UNAVAILABLE: 503,
GATEWAY_TIMEOUT: 504,
} as const;
Error Codes <-> JSON-RPC 2.0 Error Codes
Available codes & JSON-RPC code
Overriding the default HTTP method
To override the HTTP method used for queries/mutations, you can use the methodOverride option:
server/httpHandler.ts
tsx
// Your server must separately allow the client to override the HTTP method
const handler = createHTTPHandler({
router: router,
allowMethodOverride: true,
});
client/trpc.ts
tsx
import { createTRPCClient, httpLink } from '@trpc/client';
import type { AppRouter } from './server';
// The client can then specify which HTTP method to use for all queries/mutations
const client = createTRPCClient<AppRouter>({
links: [
`httpLink({`
``url: `http://localhost:3000`,``
`methodOverride: 'POST', // all queries and mutations will be sent to the tRPC Server as POST requests.`
`}),`
],
});
Dig deeper
You can read more details by drilling into the TypeScript definitions in