Define an API endpoint
Learn how to define an API endpoint in your supastarter application.
To define a new API endpoint you can either create a new router or add a new endpoint to an existing router.
This guide assumes you have already created a model in your database schema for the feature you want to create an API endpoint for. To learn how to create a model in your schema and update your database, please refer to the database documentation.
Create a new router
A router is basically a sub-path of your API. It is used to group related endpoints together.
For this example we will create a new router for the posts
feature, which will contain the common CRUD endpoints for the posts
resource.
We recommend to create a new router file in a sub-folder for the feature (or module as we call it).
For example /packages/api/modules/posts/router.ts
.
We are going to go with the first option and create a new router file in a sub-folder for the feature.
Now we can add a new endpoint to the router.
We recommend creating a new file for each endpoint to keep the code organized. Also you can easily import the endpoint as a callable function in a RSC.
In this case we are using the publicProcedure
, which means the endpoint is public and doesn't require authentication. Read more about the different types of procedures in the "protect endpoints" guide.
We have also defined the necessary properties to generate the OpenAPI specification for this endpoint.
The .output()
property is optional, but will generate an OpenAPI specification for the endpoint.
If you don't plan on using the OpenAPI specification, you can also omit the .route()
and .output()
properties.
Add endpoint to feature router
Now we need to add the new endpoint to the feature router.
Mount new router in the API
To make the new router available in the API, we need to add it to the main router in the /packages/api/orpc/router.ts
file.
Now you can use the endpoint in your application. It is available at /api/posts
.
CRUD endpoints
Now let's cover the typical CRUD endpoints for the posts
resource.
A few naming conventions we personally use:
list
->listPosts
create
->createPost
read
->findPost
update
->updatePost
delete
->deletePost
Create a post
To create a new post, we will use a protectedProcedure
to ensure the user is authenticated and also to get the current user to assign it as the author of the post:
We are wrapping the database operation in a try/catch block to handle any errors and return a 500 error to the client without passing any sensitive information to the client.
Find a post by id
Usually you want to find entities by ID or a different unique identifier.
In this case we will use the findPost
procedure to find a post by its ID.
Notice how we are using the {id}
parameter in the path for the OpenAPI route to follow the OpenAPI best practices, so you can query it like /api/posts/123
.
Update a post
To update a post, we will again use a protectedProcedure
to ensure the user is authenticated and to verify the user is the author of the post.
In case this endpoint is called without a session, the protectedProcedure
will return a 401 error.
Delete a post
For deleting a post, we will use a protectedProcedure
to ensure the user is authenticated and verify the user is the author of the post.
In case of success, we do not return any data, but in case of an error, we throw a 500 error, log the error and return a message to the client.