Rest Api Overview

Our Spring Boot task app exposes a REST API, but what is a REST API?

What's REST?

An API, or "Application Programming Interface" is a set of rules and protocols that allows different software components to communicate with each other.

Different types of API exist. Our Spring Boot app exposes a REST API.

REST, or "Representational State Transfer" is a set of conventions built on top of HTTP. We follow these conventions to create REST APIs.

Because we’re using HTTP, it means we’re using the request and response pattern. A client sends a request, and expects the server to provide a timely response.

We say the UI is a "client" of the REST API exposed by our Spring Boot app, and the Spring Boot app the "server".

It also means we’re able to use things like the HTTP verbs, headers, and response codes.

Let’s see how these things factor into a REST API.

Web Resources

When designing REST APIs it all starts with web resources.

Web resources map to your app's domain objects.

In our case we've only one domain object, the task, so we only have one web resource to consider, the task.

How do we represent a web resource in a REST API?

Formatting Web Resources

In REST, web resources are typically represented as JSON, XML, or both. We'll use JSON, which means we'll represent tasks in JSON format in requests and responses exchanged with our Spring Boot app.

Web Resources & URLs

In REST APIs we represent each web resource with a URL.

We use the plural versions of nouns when constructing a URL, for example we may represent the task web resource with this URL:

/tasks

But there's more to this convention. This URL actually represents all tasks in the app, the "collection" of tasks, not a specific task.

To represent a specific task we need to specify the task's ID in the URL. If we assume we're using UUIDs for task IDs, the URL for a specific task may be:

/tasks/60f30f9f-2231-43b6-94d4-c8f4d44f4d83

Web resources are things, so we build URLs with nouns, and avoid verbs. Instead we rely on another feature of HTTP to communicate behaviour, we use the HTTP verbs.

HTTP Verbs

REST API clients specify an HTTP verb when they make a request.

The HTTP verbs include GET, POST, PUT, PATCH, and DELETE. They allow a client to Create, Read, Update, and Delete the web resource. This is often referred to as "CRUD" behaviour.

HTTP GET

We use HTTP GET to read web resources. For example, to retrieve a single task web resource:

GET /tasks/60f30f9f-2231-43b6-94d4-c8f4d44f4d83

This returns the task with ID 60f30f9f-2231-43b6-94d4-c8f4d44f4d83 as a JSON object in the response body.

What if we want to get all the tasks in the app? The call would be:

GET /tasks

We don’t need to provide anything in the request body for a GET request.

The HTTP GET verb aligns with “read”, which is the “R” in CRUD.

HTTP POST

A client uses the HTTP POST verb to create a web resource.

To do this, the client provides a representation of the web resource to create in the request body.

An important convention with POST is that we must never allow the client to specify the ID of the web resource. Instead it’s the responsibility of the server.

For example, to create a task the URL would be POST /tasks, with a JSON representation of the task to create sent in the request body.

The HTTP POST verb aligns with “create”, which is the “C” in CRUD.

HTTP PUT

A client would use the HTTP PUT verb to create or update a web resource.

You may be wondering how PUT is different from POST. Unlike POST, with PUT you always specify the ID of the web resource in the URL, along with the full representation of the task to create in the request body.

Depending on how you implement this endpoint, you could use it for creating tasks, or updating them.

A key requirement of using PUT is that you must provide the full representation of the web resource in the request body, minus any fields managed by the server such as created.

If a task with the specified ID already exists, the app replaces its information with whatever the caller provides in the request body.

The HTTP PUT verb aligns with "create", which is the "C" in CRUD, and also "update", which is the "U" in CRUD.

You can also update web resources using the HTTP verb PATCH, but as we'll not use it in this build, we'll not go into detail about PATCH here.

HTTP DELETE

Then there’s HTTP DELETE. We specify the ID of the web resource in the URL, and use this call to delete that web resource. We don't provide anything in the request body.

Depending on the implementation, DELETE can either remove the task from the database, called a "hard delete", or add a flag on the task to mark it as deleted, called a "soft delete". Soft deletes are useful for audit purposes but mean you keep the data forever. Which you use depends on your requirements. We're using hard deletes in this build.

Status Codes

A note on status codes. These are pre-defined numeric codes the server specifies for each response that communicate the status of the operation.

As we’ll see later, the specific response code we use differs by operation, but there is a general pattern.

Response codes in the 200 range indicate the operation was successful.

Responses in the 300 range mean the server is attempting to redirect the client to a different URL.

Responses in the 400 range mean there's been an error, and it’s the responsibility of the client to resolve it before trying again.

Responses in the 500 range also mean there’s been an error, but this time it’s the responsibility of the server to resolve it.

You have some leeway when you design your REST API, but for consistency I recommend sticking to these guidelines.

Versioning

It's good practice to version your REST APIs. Here's an example of a versioned URL:

GET /api/v1/tasks

Note the /api/v1 prefix? Strictly speaking we only need the v1 part to version a REST API, but you'll often see the /api prefix used too.

The basic idea is this, if you introduce breaking changes to your REST API, rather than deploy it and cause your client code to break, you can deploy a new version and run it alongside your current version:

GET /api/v2/tasks

We use REST API versioning in the Task App REST API, let's explore it now.

The Task App REST API

Now that we've an understanding of REST, let's take a look at Task App's REST API.

It has four endpoints:

  1. Create a task.
  2. List tasks.
  3. Update a task.
  4. Delete a task.

Before we dive into the details of each endpoint, let's take a moment to consider how we'll represent errors.

REST API Errors

Things go wrong all the time, our app is no exception, so it pays to handle errors consistently.

For all errors the REST API returns a standard error format:

{ "error": "An error message" }

If the client has made a bad call then the response has the status HTTP 400 BAD REQUEST. If the error is on the server-side, the response has the status HTTP 500 INTERNAL SERVER ERROR.

This is true for every endpoint in our app, so let's explore the first.

Create a Task

A call to this endpoint creates a new task.

The HTTP verb POST is best suited for this:

POST /api/v1/tasks

When we call this endpoint we must provide a representation of the task to create in the request body:

{ "title": "Walk the Dog", "description": "Rex needs a walk!", "dueDate": "2025-12-31", "priority": "MEDIUM" }

On a success we get a response with the HTTP 201 CREATED status and a representation of the created task in the response body:

{ "id": "33b24989-746a-4b98-aa21-6e5952a4d66b", "title": "Walk the Dog", "description": "Rex needs a walk!", "dueDate": "2025-12-31", "priority": "MEDIUM", "status": "OPEN" }

Note

See that the response body has an id field and status field? The app sets these when it creates the task, the UI doesn't provide them.

List Tasks

Listing all tasks in the app is a read operation, so we use HTTP GET:

GET /api/v1/tasks

We don't provide anything in the request body for this request.

On a success the app returns a list of tasks in the response body, along with the status HTTP 200 OK:

[ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "Task A", "description": "Task A description.", "dueDate": "2025-11-01", "priority": "MEDIUM", "status": "OPEN" }, { "id": "44ddc656-4bfb-4c83-b0fa-239e863ad438", "title": "TASK B", "description": "Task B description.", "dueDate": "2025-11-02", "priority": "LOW", "status": "COMPLETED" } ]

Update a Task

Of the HTTP verbs used to update web resources, our API uses HTTP PUT:

PUT /api/v1/tasks/3fa85f64-5717-4562-b3fc-2c963f66afa6

This means we specify the task's ID in the URL, and provide a full representation of the task to be updated in the request body:

{ "title": "Walk the Fish", "description": "Frank needs his exercise!", "dueDate": "2026-01-10", "priority": "HIGH", "status": "COMPLETED" }

Well, almost a full representation. We'll omit the id field in the update request as we're already providing it in the URL.

Also note we don't provide the created or updated fields, as the server manages these fields. We can't update them manually!

The update endpoint returns a HTTP 200 OK on a success.

Delete a Task

Finally we've the delete task endpoint, which uses the HTTP verb DELETE:

DELETE /api/v1/tasks/3fa85f64-5717-4562-b3fc-2c963f66afa6

We don't provide anything in the request body, and the app returns nothing in the response body.

In fact, regardless of whether the task specified in the URL existed in the first place, the app always returns a HTTP 204 NO CONTENT.

This may seem strange, but think of it this way, regardless of whether the task existed in the first place, it definitely won't after the call!

Believe it or not, this is the recommended approach for REST API delete endpoints.

Now that we've designed the app's REST API, let's cover the Spring Boot theory we need to start coding!

Summary

  • Explored the concept of REST APIs.
  • Established the Task App's REST API.
© 2026 Devtiro Ltd. All rights reserved