How to Write a REST API in Swift in 30 Minutes: A Practical Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Swift — Not Just for Mobile Apps

Many developers are accustomed to associating Swift exclusively with iOS and macOS. However, this language has long moved beyond the Apple ecosystem. With the emergence of server-side frameworks such as Vapor and Kitura, Swift has become a full-fledged tool for backend development. In this article, we will write a complete REST API in Swift using the Vapor framework in 30 minutes. You will learn how to set up a project, create endpoints, connect a database, and handle errors. Ready? Let's go!

Step 1: Installing and Setting Up the Project

First, make sure you have Swift 5.5 or newer installed. You can check the version with the command:

swift --version

Next, install Vapor Toolbox — a utility for managing projects:

brew install vapor

Now let's create a new project:

vapor new MyAPI --template=api

This command will create a folder structure with a ready-made API template. Navigate to the project folder and run the build:

cd MyAPI
vapor build

If the build is successful, start the server:

vapor run

By default, the server will be available at http://127.0.0.1:8080. Open your browser and go to this address — you should see a welcome message.

Vapor Project Structure

  • Sources/App — the main directory with application code
  • Sources/App/Controllers — controllers for handling requests
  • Sources/App/Models — data models
  • Sources/App/routes.swift — file for registering routes
  • configure.swift — application and database configuration

Step 2: Creating the Data Model and Database

For this example, we'll create a simple API for managing a to-do list. Let's start with the data model. Create a file Todo.swift in the Sources/App/Models folder:

import Fluent
import Vapor

final class Todo: Model, Content {
    static let schema = "todos"
    
    @ID(key: .id)
    var id: UUID?
    
    @Field(key: "title")
    var title: String
    
    @Field(key: "is_completed")
    var isCompleted: Bool
    
    init() {}
    
    init(id: UUID? = nil, title: String, isCompleted: Bool = false) {
        self.id = id
        self.title = title
        self.isCompleted = isCompleted
    }
}

Now let's create a migration for the table. In the file Sources/App/Migrations/CreateTodo.swift:

import Fluent

struct CreateTodo: Migration {
    func prepare(on database: Database) -> EventLoopFuture<Void> {
        database.schema("todos")
            .id()
            .field("title", .string, .required)
            .field("is_completed", .bool, .required)
            .create()
    }
    
    func revert(on database: Database) -> EventLoopFuture<Void> {
        database.schema("todos").delete()
    }
}

Don't forget to register the migration in configure.swift:

app.migrations.add(CreateTodo())

For simplicity, we'll use SQLite (a built-in database). Add this to configure.swift:

app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite)

Step 3: Creating REST API Endpoints

Now for the most interesting part — implementing CRUD operations. Create a controller TodoController.swift in the Sources/App/Controllers folder:

import Vapor

struct TodoController: RouteCollection {
    func boot(routes: RoutesBuilder) throws {
        let todos = routes.grouped("api", "todos")
        todos.get(use: index)
        todos.post(use: create)
        todos.group(":todoID") { todo in
            todo.get(use: show)                

Blogs

Book Recommendations