Build a Blog REST API
This tutorial will walk you through building a complete blog REST API using the Restura Visual Editor. You’ll create a multi-table database with users and blog posts, along with API endpoints to manage them—all without writing SQL or endpoint handler code.
What You’ll Build
Section titled “What You’ll Build”By the end of this tutorial, you’ll have a complete blog API with:
- A
usertable for blog authors - A
posttable with a foreign key relationship to users - REST API endpoints to:
- List all users
- List all posts
- Get a single post with author information (using JOINs)
- Add a new post
- Add a new user
What You’ll Learn
Section titled “What You’ll Learn”This tutorial teaches you the Restura Visual Editor workflow:
- Use the Visual Editor to design database tables with relationships
- Use the Visual Editor to create API endpoints with JOINs
- Let Restura automatically generate SQL, types, and API handlers
- Test your API with real data
Prerequisites
Section titled “Prerequisites”- Complete the Restura Setup From Scratch guide
- Have your Restura API server running
- Have the Visual Editor open and connected to your API
Step 1: Create Your Database Tables Using the Visual Editor
Section titled “Step 1: Create Your Database Tables Using the Visual Editor”Now let’s create the database schema for our blog. We’ll create two tables: user (for authors) and post (for blog posts).
Create the User table
Section titled “Create the User table”First, let’s create a table to store blog authors.
- In the Visual Editor, click on “Database” in the left sidebar
- Click the “Add Table” button
- Name your table
user - Click “Create”
Add columns to the user table
Section titled “Add columns to the user table”Click on your new user table to open the table editor, then add these columns:
-
firstName column:
- Click the ”+” button
- Name:
firstName - Type:
VARCHAR - Length:
150 - Nullable: ✗
-
lastName column:
- Click the ”+” button
- Name:
lastName - Type:
VARCHAR - Length:
150 - Nullable: ✗
-
email column:
- Click the ”+” button
- Name:
email - Type:
VARCHAR - Length:
255 - Nullable: ✗
-
bio column:
- Click the ”+” button
- Name:
bio - Type:
TEXT - Nullable: ✓ (bio is optional)
-
role column:
- Click the ”+” button
- Name:
role - Type:
VARCHAR - Length:
50 - Nullable: ✗
Add unique indexes
Section titled “Add unique indexes”- In the table editor, scroll to the “Indexes” section
- Click the ”+” button
- Name:
user_email_unique_index - Columns: Select
email - Unique: ✓
- Name:
- Changes are automatically saved
Create the Post table
Section titled “Create the Post table”Now let’s create a table for blog posts that references the user table.
- Click “Add Table” again
- Name your table
post - Click “Create”
Add columns to the post table
Section titled “Add columns to the post table”Click on your new post table and add these columns:
-
title column:
- Click the ”+” button
- Name:
title - Type:
VARCHAR - Length:
200 - Nullable: ✗
-
content column:
- Click the ”+” button
- Name:
content - Type:
TEXT - Nullable: ✗
-
authorId column (foreign key to user):
- Click the ”+” button
- Name:
authorId - Type:
BIGINT - Nullable: ✗
-
published column:
- Click the ”+” button
- Name:
published - Type:
BOOLEAN - Default:
false - Nullable: ✗
Add an index on authorId
Section titled “Add an index on authorId”- Scroll to the “Indexes” section
- Click the ”+” button
- Name:
post_author_id_index - Columns: Select
authorId - Unique: ✗ (one author can have many posts)
- Changes are automatically saved
Preview and update your database schema
Section titled “Preview and update your database schema”- Click “Preview” in the top right of the Visual Editor
- Click the back arrow to expose the SQL statements
- Copy the SQL statements
- Paste the SQL statements into a file called
schema.sqlin your project root - Click “Submit” to update the schema file.
Add test data
Section titled “Add test data”Before applying the schema, let’s add some test data. Create a file called data.sql in your project root with the following content:
-- Insert a test userINSERT INTO "user" ("firstName", "lastName", email, bio, role)VALUES ('Jane', 'Doe', 'jane@example.com', 'Software engineer and tech blogger', 'user');This will create a test user that we can query in the next step.
Apply the schema and data to your database
Section titled “Apply the schema and data to your database”Now run the following commands to apply the schema and insert the test data:
docker compose exec -T postgres psql -U postgres -d restura < ./schema.sqldocker compose exec -T postgres psql -U postgres -d restura < ./data.sqlYou should see output confirming the tables were created and the test user was inserted.
Step 2: Create Your Endpoints Using the Visual Editor
Section titled “Step 2: Create Your Endpoints Using the Visual Editor”Now let’s create an API endpoint to list all users.
Create a new endpoint
Section titled “Create a new endpoint”- In the Visual Editor, click on “API” in the left sidebar
- Click “New”
Configure the endpoint
Section titled “Configure the endpoint”Fill in the route details:
- Name:
Get Users - Description:
Gets all users - Method:
GET - Path:
/user/list - Type:
ARRAY(returns an array of results) - Table: Select
user - Roles: Select
userandadmin(who can access this endpoint)
Configure the response
Section titled “Configure the response”In the “Response” section, add the fields you want to return:
- Click “Add Property” for each column:
- Field name:
id, Selector:user.id - Field name:
createdOn, Selector:user.createdOn - Field name:
modifiedOn, Selector:user.modifiedOn - Field name:
firstName, Selector:user.firstName - Field name:
lastName, Selector:user.lastName - Field name:
email, Selector:user.email - Field name:
role, Selector:user.role
- Field name:
Save the endpoint
Section titled “Save the endpoint”- Click “Preview Schema” in the top right
- Click “Submit” to save the changes
When you click “Submit”, the Visual Editor will update your restura.schema.json file and your Restura API will automatically reload and register the new endpoint.
Check your API server terminal—you should now see:
INFO: Restura loaded (1) endpointStep 3: Examine the Generated Schema
Section titled “Step 3: Examine the Generated Schema”Let’s take a look at what the Visual Editor created. Open your restura.schema.json file in your text editor.
You’ll see:
databasearray: Contains yourusertable definition with all columns, indexes, and constraintsendpointsarray: Contains your V1 endpoint grouproutesarray: Contains yourGET /user/listendpoint with response fieldsrolesandscopes: Access control configuration
The Visual Editor generated all of this JSON for you! You never had to write it manually.
Check the generated TypeScript types
Section titled “Check the generated TypeScript types”Restura also generated TypeScript type definitions in src/@types/:
api.d.ts- Types for your API endpoints (including the/user/listendpoint)model.d.ts- Types for your database tables (including theusertable)restura.d.ts- General Restura types
Open src/@types/api.d.ts and you’ll see type definitions for your new endpoint!
Step 4: Test Your API
Section titled “Step 4: Test Your API”Congratulations! Your API is now running. Let’s test it.
Query the user list endpoint
Section titled “Query the user list endpoint”Open a new terminal and run:
curl -X GET http://localhost:3001/api/v1/user/listYou should receive a JSON response with the test user you inserted:
[ { "id": 1, "createdOn": "2026-01-13T12:00:00.000Z", "modifiedOn": "2026-01-13T12:00:00.000Z", "firstName": "Jane", "lastName": "Doe", "email": "jane@example.com", "role": "user" }]Perfect! Your endpoint is working and returning the test user data.
Understanding what happened
Section titled “Understanding what happened”When you made the request:
- Restura received the GET request at
/api/v1/user/list - Your
authHandlervalidated the request and assigned theuserrole - Restura checked that
userrole has permission to access this endpoint (you configured this in the Visual Editor) - Restura automatically generated and executed this SQL query:
SELECT id, "createdOn", "modifiedOn", "firstName", "lastName", email, roleFROM "user"
- The results were formatted as JSON and returned
Step 5: Create the List All Posts Endpoint
Section titled “Step 5: Create the List All Posts Endpoint”Now let’s create an endpoint to list all blog posts.
Create the endpoint
Section titled “Create the endpoint”- In the Visual Editor, click on “API” in the left sidebar
- Click “New”
Configure the endpoint
Section titled “Configure the endpoint”Fill in the route details:
- Name:
Get Posts - Description:
Gets all posts - Method:
GET - Path:
/post/list - Type:
ARRAY(returns an array of results) - Table: Select
post - Roles: Select
user(who can access this endpoint)
Configure the response
Section titled “Configure the response”In the “Response” section, add the fields you want to return:
- Click “Add Property” for each column:
- Field name:
id, Selector:post.id - Field name:
createdOn, Selector:post.createdOn - Field name:
modifiedOn, Selector:post.modifiedOn - Field name:
title, Selector:post.title - Field name:
content, Selector:post.content - Field name:
authorId, Selector:post.authorId - Field name:
published, Selector:post.published
- Field name:
Save the endpoint
Section titled “Save the endpoint”- Click “Preview Schema” in the top right
- Click “Submit” to save the changes
Check your API server terminal—you should now see:
INFO: Restura loaded (2) endpointsTest the endpoint
Section titled “Test the endpoint”Open a new terminal and run:
curl -X GET http://localhost:3001/api/v1/post/listSince we haven’t added any posts yet, you should receive an empty array:
[]Perfect! The endpoint is working, but there’s no data yet. Let’s add some!
Step 6: Create the Get Single Post with Author Endpoint
Section titled “Step 6: Create the Get Single Post with Author Endpoint”Before we add data, let’s create an endpoint that demonstrates Restura’s powerful JOIN capabilities. This endpoint will return a single post along with its author’s information.
Create the endpoint
Section titled “Create the endpoint”- In the Visual Editor, click on “API” in the left sidebar
- Click “New”
Configure the endpoint
Section titled “Configure the endpoint”Fill in the route details:
- Name:
Get Post By ID - Description:
Gets a single post with author information - Method:
GET - Path:
/post/by-id - Type:
OBJECT(returns a single result) - Table: Select
post - Roles: Select
user
Add the ID parameter
Section titled “Add the ID parameter”In the “Parameters” section:
- Click “Add”
- Name:
id - Type:
BIGINT - Required: ✓
Configure the response with JOIN
Section titled “Configure the response with JOIN”In the “Response” section, we’ll add fields from both the post and user tables:
-
Post fields - Click “Add Property” for each:
- Field name:
id, Selector:post.id - Field name:
createdOn, Selector:post.createdOn - Field name:
title, Selector:post.title - Field name:
content, Selector:post.content - Field name:
published, Selector:post.published
- Field name:
-
Author fields - Click “Add Property” for each:
- Field name:
authorFirstName, Selector:user.firstName - Field name:
authorLastName, Selector:user.lastName - Field name:
authorEmail, Selector:user.email - Field name:
authorBio, Selector:user.bio
- Field name:
Add the JOIN
Section titled “Add the JOIN”- Scroll to the “Joins” section
- Click “Add Join”
- Choose the
authorIdcolumn
Add the WHERE clause
Section titled “Add the WHERE clause”- Scroll to the “Where” section
- Click “Add Statement”
- Field:
post.id - Operator:
= - Value:
$id(this references the parameter we created)
Save the endpoint
Section titled “Save the endpoint”- Click “Preview Schema” in the top right
- Click “Submit” to save the changes
- Your Restura API automatically reloads
Check your API server terminal—you should now see:
INFO: Restura loaded (3) endpointsStep 7: Create the Add New User Endpoint
Section titled “Step 7: Create the Add New User Endpoint”Now let’s create an endpoint to add new users to our blog.
Create the endpoint
Section titled “Create the endpoint”- In the Visual Editor, click on “API” in the left sidebar
- Click “New”
Configure the endpoint
Section titled “Configure the endpoint”Fill in the route details:
- Name:
Create User - Description:
Creates a new user - Method:
POST - Path:
/user/create - Type:
OBJECT(returns the created user) - Table: Select
user - Roles: Select
user
Add body parameters
Section titled “Add body parameters”In the “Parameters” section, add the following body parameters:
- Click “Add” for each:
- Name:
firstName, Type:VARCHAR, Required: ✓ - Name:
lastName, Type:VARCHAR, Required: ✓ - Name:
email, Type:VARCHAR, Required: ✓ - Name:
bio, Type:TEXT, Required: ✗ - Name:
role, Type:VARCHAR, Required: ✓
- Name:
Configure the response
Section titled “Configure the response”In the “Response” section, add the fields you want to return:
- Click “Add Property” for each column:
- Field name:
id, Selector:user.id - Field name:
createdOn, Selector:user.createdOn - Field name:
firstName, Selector:user.firstName - Field name:
lastName, Selector:user.lastName - Field name:
email, Selector:user.email - Field name:
bio, Selector:user.bio - Field name:
role, Selector:user.role
- Field name:
Save the endpoint
Section titled “Save the endpoint”- Click “Preview Schema” in the top right
- Click “Submit” to save the changes
- Your Restura API automatically reloads
Check your API server terminal—you should now see:
INFO: Restura loaded (4) endpointsStep 8: Create the Add New Post Endpoint
Section titled “Step 8: Create the Add New Post Endpoint”Finally, let’s create an endpoint to add new blog posts.
Create the endpoint
Section titled “Create the endpoint”- In the Visual Editor, click on “API” in the left sidebar
- Click “New”
Configure the endpoint
Section titled “Configure the endpoint”Fill in the route details:
- Name:
Create Post - Description:
Creates a new blog post - Method:
POST - Path:
/post/create - Type:
OBJECT(returns the created post) - Table: Select
post - Roles: Select
user
Add body parameters
Section titled “Add body parameters”In the “Parameters” section, add the following body parameters:
- Click “Add” for each:
- Name:
title, Type:VARCHAR, Required: ✓ - Name:
content, Type:TEXT, Required: ✓ - Name:
authorId, Type:BIGINT, Required: ✓ - Name:
published, Type:BOOLEAN, Required: ✗
- Name:
Configure the response
Section titled “Configure the response”In the “Response” section, add the fields you want to return:
- Click “Add Property” for each column:
- Field name:
id, Selector:post.id - Field name:
createdOn, Selector:post.createdOn - Field name:
title, Selector:post.title - Field name:
content, Selector:post.content - Field name:
authorId, Selector:post.authorId - Field name:
published, Selector:post.published
- Field name:
Save the endpoint
Section titled “Save the endpoint”- Click “Preview Schema” in the top right
- Click “Submit” to save the changes
- Your Restura API automatically reloads
Check your API server terminal—you should now see:
INFO: Restura loaded (5) endpointsStep 9: Test Your Complete API
Section titled “Step 9: Test Your Complete API”Now let’s test all of our endpoints! We already have Jane Doe in our database from the test data we inserted. Let’s create another user and some posts, then query them.
Create a second user
Section titled “Create a second user”Open a new terminal and run:
curl -X POST http://localhost:3001/api/v1/user/create \ -H "Content-Type: application/json" \ -d '{ "firstName": "John", "lastName": "Smith", "email": "john@example.com", "bio": "Full-stack developer and open source enthusiast", "role": "user" }'You should receive:
{ "id": 2, "createdOn": "2026-01-13T12:01:00.000Z", "firstName": "John", "lastName": "Smith", "email": "john@example.com", "bio": "Full-stack developer and open source enthusiast", "role": "user"}Great! Now we have two users in our database: Jane (ID 1) and John (ID 2).
Create your first blog post
Section titled “Create your first blog post”Now let’s create a blog post by Jane (user ID 1):
curl -X POST http://localhost:3001/api/v1/post/create \ -H "Content-Type: application/json" \ -d '{ "title": "Getting Started with Restura", "content": "Restura is an amazing framework for building REST APIs quickly. In this post, I will show you how to get started...", "authorId": 1, "published": true }'You should receive:
{ "id": 1, "createdOn": "2026-01-13T12:05:00.000Z", "title": "Getting Started with Restura", "content": "Restura is an amazing framework for building REST APIs quickly. In this post, I will show you how to get started...", "authorId": 1, "published": true}Create a second blog post
Section titled “Create a second blog post”Let’s create another post by John (user ID 2):
curl -X POST http://localhost:3001/api/v1/post/create \ -H "Content-Type: application/json" \ -d '{ "title": "Building Scalable APIs", "content": "When building APIs at scale, there are several key considerations to keep in mind. Let me share my experience...", "authorId": 2, "published": true }'You should receive:
{ "id": 2, "createdOn": "2026-01-13T12:06:00.000Z", "title": "Building Scalable APIs", "content": "When building APIs at scale, there are several key considerations to keep in mind. Let me share my experience...", "authorId": 2, "published": true}Create a draft post
Section titled “Create a draft post”Let’s create one more post that’s not published yet:
curl -X POST http://localhost:3001/api/v1/post/create \ -H "Content-Type: application/json" \ -d '{ "title": "Advanced Restura Techniques", "content": "This post is still being written...", "authorId": 1, "published": false }'List all users
Section titled “List all users”Now let’s query all users:
curl -X GET http://localhost:3001/api/v1/user/listYou should receive:
[ { "id": 1, "createdOn": "2026-01-13T12:00:00.000Z", "modifiedOn": "2026-01-13T12:00:00.000Z", "firstName": "Jane", "lastName": "Doe", "email": "jane@example.com", "role": "user" }, { "id": 2, "createdOn": "2026-01-13T12:00:00.000Z", "modifiedOn": "2026-01-13T12:00:00.000Z", "firstName": "John", "lastName": "Smith", "email": "john@example.com", "role": "user" }]List all posts
Section titled “List all posts”Let’s query all posts:
curl -X GET http://localhost:3001/api/v1/post/listYou should receive:
[ { "id": 1, "createdOn": "2026-01-13T12:05:00.000Z", "modifiedOn": "2026-01-13T12:05:00.000Z", "title": "Getting Started with Restura", "content": "Restura is an amazing framework for building REST APIs quickly. In this post, I will show you how to get started...", "authorId": 1, "published": true }, { "id": 2, "createdOn": "2026-01-13T12:06:00.000Z", "modifiedOn": "2026-01-13T12:06:00.000Z", "title": "Building Scalable APIs", "content": "When building APIs at scale, there are several key considerations to keep in mind. Let me share my experience...", "authorId": 2, "published": true }, { "id": 3, "createdOn": "2026-01-13T12:07:00.000Z", "modifiedOn": "2026-01-13T12:07:00.000Z", "title": "Advanced Restura Techniques", "content": "This post is still being written...", "authorId": 1, "published": false }]Get a single post with author information
Section titled “Get a single post with author information”Now let’s use our JOIN endpoint to get a post with its author’s information:
curl -X GET "http://localhost:3001/api/v1/post/by-id?id=1"You should receive:
{ "id": 1, "createdOn": "2026-01-13T12:05:00.000Z", "title": "Getting Started with Restura", "content": "Restura is an amazing framework for building REST APIs quickly. In this post, I will show you how to get started...", "published": true, "authorFirstName": "Jane", "authorLastName": "Doe", "authorEmail": "jane@example.com", "authorBio": "Software engineer and tech blogger"}Try getting the second post
Section titled “Try getting the second post”curl -X GET "http://localhost:3001/api/v1/post/by-id?id=2"You should receive:
{ "id": 2, "createdOn": "2026-01-13T12:06:00.000Z", "title": "Building Scalable APIs", "content": "When building APIs at scale, there are several key considerations to keep in mind. Let me share my experience...", "published": true, "authorFirstName": "John", "authorLastName": "Smith", "authorEmail": "john@example.com", "authorBio": "Full-stack developer and open source enthusiast"}Perfect! Your complete blog API is now working with all five endpoints:
- ✅
GET /api/v1/user/list- List all users - ✅
GET /api/v1/post/list- List all posts - ✅
GET /api/v1/post/by-id- Get a single post with author information (with JOIN) - ✅
POST /api/v1/user/create- Create a new user - ✅
POST /api/v1/post/create- Create a new post
The Restura Workflow
Section titled “The Restura Workflow”You’ve just experienced the core Restura workflow:
- Design → Use the Visual Editor to design tables and endpoints
- Generate → Restura generates schema JSON, SQL, and TypeScript types
- Deploy → Apply SQL to database, Restura handles the rest
- Use → Your API is ready with full type safety
No manual SQL queries. No endpoint handler code. No type definitions to maintain. Just design and go!
What You’ve Learned
Section titled “What You’ve Learned”In this tutorial, you:
- ✅ Created two related database tables using the Visual Editor (with foreign keys!)
- ✅ Created five REST API endpoints using the Visual Editor (no code required!)
- ✅ Built endpoints with JOINs to combine data from multiple tables
- ✅ Created both GET and POST endpoints for reading and writing data
- ✅ Examined the automatically generated schema and TypeScript types
- ✅ Tested your complete API with real data
Next Steps
Section titled “Next Steps”Now that you’ve built a complete blog API with the Visual Editor, you can:
- Learn how to create custom endpoints for complex business logic
- Explore database relationships in depth
- Learn about filtering and sorting data in your endpoints
- Set up proper authentication in your authentication handler