All APIs are type-safe using tRPC. Endpoints are available at /api/trpc/*.
| Procedure | Type | Description |
|---|---|---|
auth.login |
mutation | Authenticate user (email/LDAP) |
auth.changePassword |
mutation | Change user password |
auth.verifyToken |
query | Verify JWT token validity |
| Procedure | Type | Description |
|---|---|---|
user.list |
query | Get all users |
user.getById |
query | Get user by ID |
user.create |
mutation | Create new user |
user.update |
mutation | Update user |
user.delete |
mutation | Delete user |
| Procedure | Type | Description |
|---|---|---|
post.list |
query | Get all posts |
post.getById |
query | Get post by ID |
post.create |
mutation | Create new post |
post.update |
mutation | Update post |
post.delete |
mutation | Delete post |
| Procedure | Type | Description |
|---|---|---|
project.getMyProjects |
query | Get user's projects |
project.getAllProjects |
query | Get all visible projects |
project.searchProjects |
query | Search projects |
project.create |
mutation | Create project |
project.delete |
mutation | Delete project |
project.requestPermission |
mutation | Request project access |
'use client';
import { trpc } from '@/lib/trpc/Provider';
function MyComponent() {
// Query
const { data, isLoading } = trpc.user.list.useQuery();
// Mutation
const createUser = trpc.user.create.useMutation();
const handleCreate = async () => {
await createUser.mutateAsync({
name: 'John Doe',
email: 'john@example.com',
});
};
return <div>...</div>;
}import { db } from '@/lib/db';
import { users } from '@/lib/db/schema';
export const userRouter = router({
list: publicProcedure.query(async () => {
return await db.select().from(users);
}),
create: publicProcedure
.input(z.object({
name: z.string(),
email: z.string().email(),
}))
.mutation(async ({ input }) => {
return await db.insert(users).values(input).returning();
}),
});POST /api/queue/add
Add a job to the queue:
curl -X POST http://localhost:3000/api/queue/add \
-H "Content-Type: application/json" \
-d '{
"queueName": "default",
"jobName": "my-job",
"data": { "key": "value" }
}'See WebSocket Flow for complete documentation.
Connect: ws://localhost:3001
Message Types:
subscribe- Subscribe to channelunsubscribe- Unsubscribe from channelbroadcast- Send message to channelping/pong- Keep-alive
For complete API details, see:
- tRPC Endpoints - All tRPC procedures
- WebSocket Protocol - Real-time messaging
- Queue API - Background job management
tRPC provides end-to-end type safety:
// Server defines types
const createUser = publicProcedure
.input(z.object({
name: z.string(),
email: z.string().email(),
}))
.mutation(async ({ input }) => {
// input is typed: { name: string; email: string }
return await db.insert(users).values(input).returning();
});
// Client gets full type inference
const user = await trpc.user.create.mutate({
name: 'John',
email: 'john@example.com',
// TypeScript error if wrong fields or types!
});
// user is typed as UserProtected procedures require authentication token:
// Protected procedure
const getProfile = protectedProcedure.query(async ({ ctx }) => {
// ctx.user is guaranteed to exist
return await db.select()
.from(users)
.where(eq(users.id, ctx.user.userId));
});Tokens are automatically included from localStorage.