Build Your First API - Blog REST API
This tutorial will walk you through building a complete blog REST API from scratch using Restura. You’ll create a multi-table database with users and blog posts, along with API endpoints to manage them—all using the Visual Editor.
What You’ll Build
Section titled “What You’ll Build”By the end of this tutorial, you’ll have a complete blog API with:
- An Express application with Restura integrated
- A local PostgreSQL database running in Docker
- The Restura Visual Editor running and connected to your API
- 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 posts by a specific author
- 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 real Restura workflow:
- Set up the infrastructure (Express, PostgreSQL, Restura)
- 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
Prerequisites
Section titled “Prerequisites”- Node.js 18+ installed
- Docker Compose installed
- Git installed
- A terminal and text editor
- Basic knowledge of JavaScript/TypeScript
Step 1: Create an Express Application
Section titled “Step 1: Create an Express Application”First, let’s create a new Express project.
Create a new project directory
Section titled “Create a new project directory”Run the following commands in your terminal:
mkdir restura-democd restura-demonpm init -ynpm install expressmkdir restura-democd restura-demopnpm initpnpm add expressmkdir restura-democd restura-demoyarn init -yyarn add expressmkdir restura-democd restura-demobun init -ybun add expressInstall TypeScript (Optional but Recommended)
Section titled “Install TypeScript (Optional but Recommended)”If you want to use TypeScript, install it now:
npm install -D typescript @types/express @types/nodenpx tsc --initpnpm add -D typescript @types/express @types/nodepnpx tsc --inityarn add -D typescript @types/express @types/nodeyarn tsc --initbun add -D @types/expressCreate an entry file
Section titled “Create an entry file”Create a file called server.ts (or server.js if not using TypeScript):
We’ll add content to this file after installing Restura.
Step 2: Install Restura
Section titled “Step 2: Install Restura”Now install the Restura Engine:
npm install @restura/corepnpm add @restura/coreyarn add @restura/corebun add @restura/coreStep 3: Initialize Restura in Your Express App
Section titled “Step 3: Initialize Restura in Your Express App”Open your server.ts (or server.js) file and add the following code:
import { PsqlPool, restura, type OnValidAuthenticationCallback, type RsRequest, type RsResponse } from '@restura/core';import express from 'express';
const app = express();
// Create a PostgreSQL connection pool// We'll use these credentials with our Docker setup belowconst pool = new PsqlPool({host: "localhost",port: 5432,user: "postgres",password: "postgres",database: "restura",});
// Define an authentication handler// For now, we'll allow all requests as the 'user' roleconst authHandler = async (req: RsRequest<unknown>, res: RsResponse<unknown>, onValid: OnValidAuthenticationCallback) => {onValid({ role: 'user', scopes: [] });};
// Initialize Resturaawait restura.init(app, authHandler, pool);
app.listen(3001, () => {console.log('Server is running on http://localhost:3001');});const { PsqlPool, restura } = require('@restura/core');const express = require('express');
const app = express();
// Create a PostgreSQL connection pool// We'll use these credentials with our Docker setup belowconst pool = new PsqlPool({host: "localhost",port: 5432,user: "postgres",password: "postgres",database: "restura",});
// Define an authentication handler// For now, we'll allow all requests as the 'user' roleconst authHandler = async (req, res, onValid) => {onValid({ role: 'user', scopes: [] });};
// Initialize Restura(async () => {await restura.init(app, authHandler, pool);
app.listen(3001, () => {console.log('Server is running on http://localhost:3001');});})();Add a start script
Section titled “Add a start script”Update your package.json to add a start script:
{ "type": "module", "scripts": { "start": "node server.ts" }}{ "scripts": { "start": "node server.js" }}Step 4: Create Configuration Files
Section titled “Step 4: Create Configuration Files”Restura needs two configuration files to work.
Create restura.config.mjs
Section titled “Create restura.config.mjs”Create a restura.config.mjs file in your project root:
export default { logger: { level: "info" // Options: "debug", "info", "warn", "error" }, restura: { authToken: "12345" // Used by the Visual Editor to connect to your API }}Create an empty schema file
Section titled “Create an empty schema file”Create a restura.schema.json file in your project root.
Add the following content to the file:
{ "customTypes": [], "database": [], "endpoints": [ { "baseUrl": "/api/v1", "description": "V1 Endpoints", "name": "V1", "routes": [] } ], "globalParams": ["userId"], "roles": ["anonymous", "user", "admin"], "scopes": ["read:user", "write:user"]}This creates a minimal schema with an empty database and endpoint structure that the Visual Editor can work with.
Step 5: Setup a Local PostgreSQL Database
Section titled “Step 5: Setup a Local PostgreSQL Database”For this tutorial, we’ll use Docker Compose to run a local PostgreSQL database.
Create a docker-compose.yml file in the root of your project with the following content:
services: postgres: image: postgres:16 ports: - 5432:5432 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: resturaThen run the following command to start the local PostgreSQL database:
docker compose up -dThe database is now running in the background. The credentials in your server.ts file match this setup, so you’re ready to go!
Step 6: Start Your Restura API
Section titled “Step 6: Start Your Restura API”Now let’s start your API server. Open a terminal and run:
npm start # or pnpm start, yarn start, bun start, etc.You should see output like:
INFO [2026-01-12 04:25:34.373]: Restura loaded (0) endpointINFO [2026-01-12 04:25:34.379]: Restura Engine InitializedINFO [2026-01-12 04:25:34.495]: Successfully connected to database triggersINFO [2026-01-12 04:25:34.498]: Connected to PostgreSQL databaseServer is running on http://localhost:3001Keep this terminal running. Your API server needs to be running for the Visual Editor to connect to it.
Step 7: Setup the Visual Editor
Section titled “Step 7: Setup the Visual Editor”The Visual Editor is a web application that lets you visually design your database tables and API endpoints.
Once you’ve completed the Visual Editor setup and signed in, you should see an empty dashboard with options to create database tables and endpoints.
Step 8: Create Your Database Tables Using the Visual Editor
Section titled “Step 8: 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 ”+ Add Column”
- Name:
firstName - Type:
VARCHAR - Length:
150 - Nullable: ✗
-
lastName column:
- Click ”+ Add Column”
- Name:
lastName - Type:
VARCHAR - Length:
150 - Nullable: ✗
-
email column:
- Click ”+ Add Column”
- Name:
email - Type:
VARCHAR - Length:
255 - Nullable: ✗
-
bio column:
- Click ”+ Add Column”
- Name:
bio - Type:
TEXT - Nullable: ✓ (bio is optional)
-
role column:
- Click ”+ Add Column”
- 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 ”+ Add Index”
- Name:
user_email_unique_index - Columns: Select
email - Unique: ✓
- Name:
- Click “Save” to save the user table
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 ”+ Add Column”
- Name:
title - Type:
VARCHAR - Length:
200 - Nullable: ✗
-
content column:
- Click ”+ Add Column”
- Name:
content - Type:
TEXT - Nullable: ✗
-
authorId column (foreign key to user):
- Click ”+ Add Column”
- Name:
authorId - Type:
BIGINT - Nullable: ✗
-
published column:
- Click ”+ Add Column”
- 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 ”+ Add Index”
- Name:
post_author_id_index - Columns: Select
authorId - Unique: ✗ (one author can have many posts)
- Click “Save”
Save and apply the schema
Section titled “Save and apply the schema”- Click “Save” in the top right of the Visual Editor
- The Visual Editor will update your
restura.schema.jsonfile automatically - Your Restura API will detect the change and reload
Generate and apply the SQL
Section titled “Generate and apply the SQL”- In the Visual Editor, go to “Database” → “Generate SQL”
- Copy the generated SQL
- In your project terminal, create a file called
schema.sqland paste the SQL - Run this command to apply it:
docker compose exec -T postgres psql -U postgres -d restura < ./schema.sqlAdd sample data
Section titled “Add sample data”Let’s add a sample user to test with. Run this command:
docker compose exec -T postgres psql -U postgres -d restura -c "INSERT INTO public.\"user\" ( \"firstName\", \"lastName\", email, role) VALUES ( 'Test', 'User', 'test@restura.io', 'user');"Now let’s add a sample blog post. Run this command:
docker compose exec -T postgres psql -U postgres -d restura -c "INSERT INTO public.post ( title, content, \"authorId\") VALUES ( 'Welcome to My Blog', 'This is my first blog post using Restura! It''s amazing how easy it is to build APIs without writing SQL queries or endpoint handlers.', 1);"Step 9: Create Your First API Endpoint
Section titled “Step 9: Create Your First API Endpoint”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 Field” 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 “Save” in the top right
- The Visual Editor updates your
restura.schema.jsonfile - Your Restura API automatically reloads and registers the new endpoint
Check your API server terminal—you should now see:
INFO: Restura loaded (1) endpointStep 10: Examine the Generated Schema
Section titled “Step 10: 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 11: Test Your API
Section titled “Step 11: 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 your user data:
[ { "id": 1, "createdOn": "2026-01-12T12:00:00.000Z", "modifiedOn": "2026-01-12T12:00:00.000Z", "firstName": "Test", "lastName": "User", "email": "test@restura.io", "role": "user" }]🎉 It works! You just built a complete REST API without writing any SQL queries or endpoint handler code!
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 the ‘user’ role - Restura checked that ‘user’ role 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
Finish the API
Section titled “Finish the API”Now that you’ve built your first endpoint, try adding these features using the Visual Editor:
- Create a GET endpoint at
/post/listthat returns all posts - Create a GET endpoint at
/post/by-authorthat filters posts by author - Create a GET endpoint at
/post/by-idthat returns a single post by ID
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:
- ✅ Set up an Express application with Restura
- ✅ Created a local PostgreSQL database with Docker
- ✅ Connected the Visual Editor to Restura
- ✅ Created a database table using the Visual Editor (no manual JSON editing!)
- ✅ Created a REST API endpoint using the Visual Editor (no code required!)
- ✅ Examined the automatically generated schema and TypeScript types
- ✅ Tested your endpoint and saw it work