name: tsrpc-api description: Use when creating new TSRPC API endpoints, adding new functionality, or implementing request-response interfaces. Triggers on phrases like create API, add endpoint, implement interface, new service tags: ["tsrpc","api","backend"]
TSRPC API Creation Guide
This skill helps you create new API endpoints in a TSRPC project following best practices.
Quick Start
To create a new API, you need to complete 3 steps:
- Define Protocol - Create request/response types in
shared/protocols/ - Implement API - Create the API handler in
api/ - Generate ServiceProto - Run
npx tsrpc-cli proto --input ./src/shared/protocols --output ./src/shared/protocols/serviceProto.ts
Step 1: Define Protocol
Create a new file shared/protocols/Pt{ApiName}.ts:
// shared/protocols/PtHello.ts
// Request type - what the client sends
export interface ReqHello {
name: string;
}
// Response type - what the server returns
export interface ResHello {
reply: string;
time: Date;
}
Protocol Naming Convention
- File name:
Pt{ApiName}.ts(e.g.,PtHello.ts,PtUserLogin.ts) - Request interface:
Req{ApiName} - Response interface:
Res{ApiName}
Supported Types
TSRPC supports all TypeScript types including:
- Primitives:
string,number,boolean,null,undefined - Objects and Arrays
- Union Types:
string | number - Intersection Types:
A & B - Utility Types:
Pick<T>,Omit<T>,Partial<T> - Special types:
Date,ArrayBuffer,ObjectId(MongoDB)
Step 2: Implement API
Create a new file api/Api{ApiName}.ts:
// api/ApiHello.ts
import { ApiCall } from "tsrpc";
import { ReqHello, ResHello } from "../shared/protocols/PtHello";
export async function ApiHello(call: ApiCall<ReqHello, ResHello>) {
// Access request data via call.req
const { name } = call.req;
// Return success response
call.succ({
reply: "Hello, " + name,
time: new Date()
});
}
API Implementation Patterns
Success Response:
call.succ({ /* response data */ });
Error Response:
call.error('Error message');
// or with error code
call.error('Error message', { code: 'INVALID_INPUT' });
Access Connection Info (WebSocket):
// Get client connection
const conn = call.conn;
// Get current user from session
const currentUser = call.conn.currentUser;
Step 3: Generate ServiceProto
After creating the protocol and API files, regenerate the service protocol:
cd backend && npm run proto
# Or: npx tsrpc-cli proto --input ./src/shared/protocols --output ./src/shared/protocols/serviceProto.ts
⚠️ IMPORTANT: serviceProto.ts is auto-generated. NEVER edit it manually - your changes will be lost when regenerating. Always modify Pt*.ts files instead.
Client-Side Usage
// Call the API from client
const result = await client.callApi('Hello', {
name: 'World'
});
if (result.isSucc) {
console.log(result.res.reply); // "Hello, World!"
console.log(result.res.time); // Date object
} else {
console.error(result.err.message);
}
Best Practices
- Type Safety: Always define explicit types for request and response
- Validation: TSRPC automatically validates incoming requests against the protocol types
- Error Handling: Use
call.error()for business logic errors - Async Operations: API handlers are async functions, use
awaitfor database operations - Logging: Use
call.loggerfor request-scoped logging
Common Patterns
API with Database
export async function ApiGetUser(call: ApiCall<ReqGetUser, ResGetUser>) {
const user = await db.collection('users').findOne({
_id: new ObjectId(call.req.userId)
});
if (!user) {
return call.error('User not found');
}
call.succ({ user });
}
API with Authentication Check
export async function ApiUpdateProfile(call: ApiCall<ReqUpdateProfile, ResUpdateProfile>) {
// Check if user is logged in (requires auth flow)
if (!call.conn.currentUser) {
return call.error('Please login first', { code: 'NEED_LOGIN' });
}
// Proceed with update...
call.succ({ success: true });
}
See Also
- Run
/tsrpc-flowto add middleware (authentication, logging, etc.)