Build a REST API with Python and Flask

Build a Book Collection API with full CRUD operations using Flask.

Introduction

30 Second Summary

Every time you check the weather, scroll social media, or order food, your app is sending requests to an API behind the scenes. APIs are how software talks to other software.

In this project, you will build a Book Collection API from scratch using Python and Flask, then test it with Postman to see exactly how requests and responses flow.

What You'll Build

You will send HTTP requests to your running API and watch it respond with book data in real time, proving you can build the same kind of service that powers every modern app.

By the end of this project, you'll have:

  • A running Book Collection API that responds to requests with JSON data, letting you fetch your entire library or look up a single book by its ID.
  • The ability to create, update, and delete books through HTTP requests, completing a full set of CRUD operations.
  • Proper error handling with HTTP status codes so your API responds correctly when someone requests a book that does not exist or sends incomplete data.
  • Secret Mission: Add search and filtering so you can find books by author or title.

Are there any prerequisites?

You just need VS Code and Postman installed on your computer. This project walks you through installing Python and everything else from scratch.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters.

Install Python and Set Up Your Project

To build your Book Collection API, you need Python installed on your machine and a project environment ready to go.

In this step, you will install Python 3.13, create a dedicated project folder, set up a virtual environment, and install Flask.

In this step, get ready to:
  • Install Python 3.13 and verify it works from your terminal.
  • Create a project folder with a virtual environment.
  • Install Flask inside your virtual environment.
Install Python 3.13

Python is the programming language your API will be written in. You need version 3.13 installed and available from your terminal.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type VS Code and press Enter to open it.
  • Open the integrated terminal by pressing Ctrl+`.
  • Check if Python is already installed by running this command:
python --version

Look at what your terminal prints and pick the tab that matches your result.

✔️ I see version 3.13 or higher

You already have Python 3.13 installed. You are ready to create your project folder.

ⓧ I see an older version

You have Python installed, but you need version 3.13 for this project. Download and install the latest 3.13 release from the official Python website.

Windows

  • Open https://www.python.org/downloads/windows/ in your browser.
  • Click the link for Python 3.13.15 and download the Windows installer (64-bit).
  • Run the installer.
  • Check the box labeled Add python.exe to PATH at the bottom of the first screen.
  • Click Install Now.

macOS

  • Open https://www.python.org/downloads/macos/ in your browser.
  • Click the link for Python 3.13.15 and download the macOS 64-bit universal2 installer.
  • Open the downloaded .pkg file and follow the installation prompts.

After the installation finishes, close and reopen your VS Code terminal. Then run python --version again to confirm you see 3.13.

ⓧ Command not found

Python is not installed yet. Download and install it from the official website.

Windows

  • Open https://www.python.org/downloads/windows/ in your browser.
  • Click the link for Python 3.13.15 and download the Windows installer (64-bit).
  • Run the installer.
  • Check the box labeled Add python.exe to PATH at the bottom of the first screen.
  • Click Install Now.

macOS

  • Open https://www.python.org/downloads/macos/ in your browser.
  • Click the link for Python 3.13.15 and download the macOS 64-bit universal2 installer.
  • Open the downloaded .pkg file and follow the installation prompts.

After the installation finishes, close and reopen your VS Code terminal. Then run python --version again to confirm you see a version starting with 3.13.

Still seeing command not found after installing?

On Windows, make sure you checked Add python.exe to PATH during installation. If you missed it, re-run the installer, select Modify, and enable the PATH option.

On macOS, try running python3 --version instead. If that works, use python3 in place of python for the rest of this project.

Help me troubleshoot my Python installation.

Create your project folder and virtual environment

A virtual environment keeps your project's packages separate from the rest of your system. This prevents version conflicts between different projects.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir book-api
cd book-api
  • Confirm you are inside the book-api folder by running:
ls

The output should be empty since the folder is brand new. That is expected.

  • Create a virtual environment and activate it by running these commands:

Windows

python -m venv venv
venv\Scripts\activate

macOS

python3 -m venv venv
source venv/bin/activate

You should see (venv) appear at the beginning of your terminal prompt. This confirms the virtual environment is active.

What is a virtual environment?

A virtual environment is an isolated space on your computer where you can install Python packages without affecting anything else. Every package you install while (venv) is active only lives inside this project.

Don't see (venv) in your prompt?

On Windows, if you see an error about execution policies, run this command first and then try the activate command again:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

On macOS, make sure you used source venv/bin/activate with forward slashes.

Help me activate my virtual environment.

Install Flask

Flask is the lightweight web framework that will power your API. It handles routing HTTP requests to your Python code.

  • Install Flask in your virtual environment by running this command:
pip install Flask==3.1.3

What does this command do?

The pip install command downloads and installs Python packages. The ==3.1.3 part pins the exact version so everyone following this project uses the same Flask release.

Before you verify, what do you think pip show flask will display?

  • Confirm Flask is installed by running:
pip show flask

You should see output that includes Version: 3.1.3. This confirms Flask is installed and ready to use.

Seeing "No matching distribution found"?

Make sure your virtual environment is active. You should see (venv) at the start of your terminal prompt. If it is missing, run the activate command from the previous substep again.

Also confirm you are connected to the internet, since pip needs to download the package.

Help me install Flask in my virtual environment.

Your environment is ready. Next up, you will write your first Flask endpoint and see your API respond to a request.

Create Your First API Endpoint

Your environment is ready with Python and Flask installed. Now it is time to put Flask to work.

The fastest way to understand what an API does is to see one respond to a request. In this step, you will create the smallest possible Flask API and see it work immediately.

In this step, get ready to:
  • Write a minimal Flask application that returns JSON data.
  • Run your API and test it in both your browser and Postman.
Write your Flask application

An endpoint is a specific URL that your API responds to. You will create one endpoint at the root path / that returns a welcome message as JSON.

  • In VS Code, click File in the top menu bar.
  • Click New File.
  • Name the file app.py and save it inside your book-api folder.
  • Copy the following code into app.py:
from flask import Flask, jsonify, request

# Create the Flask application instance
app = Flask(__name__)

# Define a route for the home page
@app.route('/')
def home():
    return jsonify({"message": "Welcome to my Book API!"})

# Run the server when this file is executed directly
if __name__ == '__main__':
    app.run(debug=True)

What does this code do?

  • from flask import Flask, jsonify, request imports the tools you need from Flask. Flask creates the app, jsonify converts Python data into JSON responses, and request will be used in later steps to read incoming data.
  • app = Flask(__name__) creates your Flask application instance.
  • @app.route('/') tells Flask to call the home() function when someone visits the root URL.
  • app.run(debug=True) starts the server with auto-reload enabled. Any changes you save to the file take effect without restarting.

Never name your file flask.py

Naming your file flask.py would conflict with the Flask package itself. Python would try to import your file instead of the real Flask library, causing confusing errors.

  • Save app.py by pressing Cmd+S (macOS) or Ctrl+S (Windows).

✔️ Awesome, I've got everything!

Great. Double check you have saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete app.py at this point:

from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/')
def home():
    return jsonify({"message": "Welcome to my Book API!"})

if __name__ == '__main__':
    app.run(debug=True)
Run and test your API

Your code is written. Now you will start the server and send it your first HTTP request.

  • Start your API server by running this command in your terminal:
python app.py

What should I see?

Your terminal will display something like:

 * Serving Flask app 'app'
 * Debug mode: on
 * Running on http://127.0.0.1:5000
 * Debugger is active!
 * Debugger PIN: xxx-xxx-xxx

The server is now running and waiting for requests. Your terminal stays occupied by the server process. Do not close this terminal or press Ctrl+C until you are done testing.

Before you open the URL, what do you think the browser will show?

  • Open your browser and go to http://127.0.0.1:5000/.

You should see {"message": "Welcome to my Book API!"} displayed in the browser. That is your Flask API responding to a GET request with JSON data.

  • Switch to Postman.
  • Set the method to GET.
  • Enter http://127.0.0.1:5000/ in the URL bar.
  • Click Send.

Postman displays the same JSON response plus a 200 OK status code in the response panel. That 200 means the request succeeded.

Not seeing a response?

  • Make sure your terminal still shows the server running. If you accidentally closed it or pressed Ctrl+C, run python app.py again.
  • Check that you saved app.py before running the command. Unsaved changes are not picked up.
  • Confirm the URL is exactly http://127.0.0.1:5000/ with no typos or extra characters.

Still stuck? Help me debug why my Flask server is not responding to requests.

Your first API endpoint is live and responding to requests. Next up, you will add real data to your API by serving an actual book collection.

Serve Your Book Collection

Your API is live and returning a welcome message. That proves Flask is working, but a welcome message is not useful data.

In this step, you will add actual book data to your API and create endpoints to retrieve it. This is where your API starts doing real work. You will also discover a problem when you request a book that does not exist.

In this step, get ready to:
  • Add a book collection to your API and serve it as JSON.
  • Create an endpoint to look up a single book by its ID.
  • Discover what goes wrong when you request a book that does not exist.
Add your book data and list endpoint

Your API needs data to serve. You will add a list of three books directly in your code, then create an endpoint that returns them all as JSON.

  • In VS Code, open app.py from the book-api folder.
  • Find the line that says app = Flask(__name__). Add the following book data directly below it:
books = [
    {"id": 1, "title": "The Great Gatsby", "author": "F. Scott Fitzgerald"},
    {"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"},
    {"id": 3, "title": "1984", "author": "George Orwell"}
]

What does this code do?

This is a Python list of dictionaries. Each dictionary represents one book with three fields: id, title, and author.

The data lives in memory. It resets every time you restart the server. For learning REST API concepts, this is simpler than setting up a database.

  • Now add a new endpoint below your existing home() function. This endpoint returns the full list of books:
@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)

What does this code do?

The @app.route('/books', methods=['GET']) decorator tells Flask to call this function when someone sends a GET request to /books.

The jsonify(books) function converts your Python list into a JSON response that any client can read.

  • Save app.py.
  • Your Flask server auto-reloads when you save because you enabled debug=True. Switch to Postman and send a GET request to:
http://127.0.0.1:5000/books
  • You should see a JSON array containing all 3 books with their IDs, titles, and authors.

Not seeing 3 books in Postman?

  • Make sure your books list is placed between app = Flask(__name__) and the @app.route('/') decorator. If it appears inside a function, other functions cannot access it.
  • Check your terminal for error messages. A missing comma between book dictionaries or a missing bracket will crash the server.
  • Confirm the request method in Postman is set to GET, not POST.

Why isn't my /books endpoint returning data?

Look up a single book by ID

Returning all books is useful, but clients often need one specific book. You will add an endpoint that accepts a book ID in the URL and returns just that book.

  • In app.py, add this new endpoint below your get_books() function:
@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
    # Find the book with a matching ID, or None if not found
    book = next((b for b in books if b['id'] == book_id), None)
    return jsonify(book)

What does this code do?

The <int:book_id> part of the URL is a variable. Flask captures whatever integer the user puts in the URL and passes it to the function as book_id.

The next() function searches through the books list for a matching ID. If no match is found, it returns None.

  • Save app.py.
  • In Postman, send a GET request to:
http://127.0.0.1:5000/books/1
  • You should see a single book object: The Great Gatsby by F. Scott Fitzgerald.

Seeing a 404 Not Found error?

  • Make sure the URL is /books/1 (not /book/1). The route uses the plural books.
  • Check that <int:book_id> is spelled exactly as shown, including the angle brackets in your route decorator.

Why is my /books/1 endpoint returning a 404?

Discover the problem with missing books

Your endpoint works for books that exist. But what happens when someone requests a book ID that is not in your collection?

  • Before you send this request, predict what you think will happen. Will the API return an error? A blank response? Something else?
  • In Postman, send a GET request to:
http://127.0.0.1:5000/books/99

Look at the response body and the status code in the top right corner of the Postman response panel.

You will see null in the body and a 200 OK status. That is the wrong response for a missing resource.

Why is this wrong?

HTTP status code 200 means "everything went fine." But nothing went fine. The book does not exist.

The correct response for a missing resource is 404 Not Found. Right now your endpoint blindly returns whatever it finds, even None. Any client consuming this API would think the request succeeded. You will fix this in the next step.

✔️ Awesome, I've got everything!

Great. Double check you have saved app.py and confirmed both the /books and /books/1 responses work correctly.

ⓧ I'd like to double check the full code

Here is the full app.py at this point:

from flask import Flask, jsonify, request

app = Flask(__name__)

books = [
    {"id": 1, "title": "The Great Gatsby", "author": "F. Scott Fitzgerald"},
    {"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"},
    {"id": 3, "title": "1984", "author": "George Orwell"}
]

@app.route('/')
def home():
    return jsonify({"message": "Welcome to my Book API!"})

@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)

@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
    book = next((b for b in books if b['id'] == book_id), None)
    return jsonify(book)

if __name__ == '__main__':
    app.run(debug=True)

Your API now serves book data and can look up individual books. But it has a gap: requesting a non-existent book returns a misleading 200 OK. Next up, you will fix this with proper error handling and add the ability to create new books.

Handle Errors and Create Books

Your API is serving book data, but in the last step you noticed a problem: requesting a book that doesn't exist returns null with a 200 OK status.

A 200 status code means "everything is fine." Sending that for a missing resource misleads anyone consuming your API. In this step, you'll fix that with proper HTTP status codes, then add the ability to create new books.

In this step, get ready to:
  • Fix the GET endpoint to return a 404 error for missing books.
  • Add a POST endpoint that creates new books with validation.
  • Test error handling and book creation in Postman.
Fix the missing book response

Right now, your get_book function returns whatever it finds. If the book ID doesn't match anything, the result is None. HTTP has a dedicated status code for "not found" resources: 404.

  • In app.py, find the get_book function. Look for these two lines inside it:
    book = next((b for b in books if b['id'] == book_id), None)
    return jsonify(book)
  • Replace return jsonify(book) with a check that returns a 404 error when book is None. The complete function should now look like this:
@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
    book = next((b for b in books if b['id'] == book_id), None)
    if book is None:
        return jsonify({"error": "Book not found"}), 404
    return jsonify(book)

What does this code do?

The if book is None check catches the case where no book matches the requested ID.

Returning a tuple (response, status_code) is how Flask sends a custom status code. The 404 tells the client that the resource doesn't exist, instead of pretending everything is fine with a 200.

  • Save app.py. Flask's debug mode auto-reloads your server, so the changes take effect immediately.

Before you test this, what do you think Postman will show when you request a book ID that doesn't exist?

  • In Postman, send a GET request to this URL:
http://127.0.0.1:5000/books/99

You should see a 404 Not Found status in the top-right of the response panel, with this JSON body:

{"error": "Book not found"}

Still seeing 200 OK?

  • Make sure you saved app.py after making the change. Flask only reloads when the file is saved.
  • Check that your if book is None: line is indented inside the get_book function, not outside it.
  • If the server crashed, restart it with python app.py in your terminal.

Why is my API still returning 200 for missing books?

Add a POST endpoint to create books

Your API can read books, but it can't grow. A POST request sends new data to the server. You'll add an endpoint that accepts a book's title and author in the request body, then adds it to your collection.

  • In app.py, add this new function below the get_book function and above the if __name__ == '__main__': line:
@app.route('/books', methods=['POST'])
def create_book():
    # Read JSON data from the request body
    data = request.get_json()
    # Validate that title and author are present
    if not data or 'title' not in data or 'author' not in data:
        return jsonify({"error": "Title and author are required"}), 400
    # Build the new book with an auto-incremented ID
    new_book = {
        "id": len(books) + 1,
        "title": data['title'],
        "author": data['author']
    }
    books.append(new_book)
    return jsonify(new_book), 201

What does this code do?

  • request.get_json() parses the JSON body sent with the request. If the client didn't send JSON, this returns None.
  • The if not data check catches missing or malformed bodies. The 'title' not in data check ensures both required fields are present. If validation fails, the API returns a 400 Bad Request status.
  • The 201 status code means "Created." It tells the client that a new resource was successfully made.
  • Save app.py.
Test book creation in Postman

Time to create a book. You'll configure Postman to send a POST request with a JSON body containing the new book's details.

  • In Postman, change the method dropdown from GET to POST.
  • Set the URL to:
http://127.0.0.1:5000/books
  • Click the Body tab below the URL bar.
  • Select the raw radio button.
  • In the dropdown to the right of raw, change it from Text to JSON.
  • Paste this JSON into the body area:
{
    "title": "Brave New World",
    "author": "Aldous Huxley"
}

What status code do you think will come back when you send a valid new book?

  • Click Send.

You should see a 201 Created status with your new book returned, including its auto-generated id:

{
    "author": "Aldous Huxley",
    "id": 4,
    "title": "Brave New World"
}
  • Now test the validation. Clear the body and paste this incomplete JSON (missing the author):
{
    "title": "Incomplete Book"
}
  • Click Send.

You should see a 400 Bad Request status with {"error": "Title and author are required"}.

  • Finally, confirm your new book is in the collection. Change the method back to GET and send the request to http://127.0.0.1:5000/books.

You should see all 4 books returned, including "Brave New World" at the end of the list.

Getting a 405 Method Not Allowed?

  • Make sure Postman's method dropdown says POST, not GET. A GET to /books works fine, but POST only works if your create_book function is defined.
  • Check that the Body dropdown says JSON, not Text. Flask's request.get_json() returns None if the content type isn't set to JSON.
  • Verify your @app.route('/books', methods=['POST']) decorator is on the line directly above def create_book():.

Why is my Flask POST endpoint returning an error?

✔️ Awesome, I've got everything!

Great. Make sure you've saved app.py and your server is still running.

ⓧ I'd like to double check the full code

Scroll up and confirm your app.py contains each of these sections, in order:

  • The from flask import Flask, jsonify, request import line at the top.
  • The books list with 3 hardcoded books.
  • The home function at the / route.
  • The get_books function at GET /books.
  • The updated get_book function at GET /books/<int:book_id> with the if book is None check and 404 return.
  • The new create_book function at POST /books with validation and 201 return.
  • The if __name__ == '__main__': block at the bottom.

Your API now speaks the language of proper HTTP. It says "not found" when something is missing and "created" when something new is made. Next up, you'll complete the picture with Update and Delete operations.

Update and Delete Books

Your API now handles errors properly and lets you create new books. That covers the C (Create) and R (Read) of CRUD.

In this step, you'll complete the picture by adding Update and Delete. Once these are in place, your API can manage the full lifecycle of a book from creation to removal.

In this step, get ready to:
  • Add a PUT endpoint to update book details.
  • Add a DELETE endpoint to remove books.
  • Test the full CRUD cycle in Postman.
Add the PUT endpoint for updating books

The PUT method tells the server to replace or update an existing resource. Your endpoint will find a book by its ID, update the fields the client sends, and return the updated book.

  • In app.py, scroll to the bottom of your file and find this line:
  • Add the following PUT endpoint above that line:
if __name__ == '__main__':
  • Add the following PUT endpoint above that line:
@app.route('/books/<int:book_id>', methods=['PUT'])
def update_book(book_id):
    # Find the book by ID
    book = next((b for b in books if b['id'] == book_id), None)
    if book is None:
        return jsonify({"error": "Book not found"}), 404
    # Update fields from request data, keeping existing values as defaults
    data = request.get_json()
    book['title'] = data.get('title', book['title'])
    book['author'] = data.get('author', book['author'])
    return jsonify(book)

What does this code do?

This endpoint uses the same book-lookup pattern you built for the GET single-book endpoint. The difference is what happens after the book is found.

  • data.get('title', book['title']) pulls the new title from the request body. If the client did not send a title, it keeps the existing one.
  • This means the client can update just the title, just the author, or both at once.
  • Save app.py.
  • Switch back to Postman and create a new request.
  • Set the method to PUT.
  • Set the URL to http://127.0.0.1:5000/books/1.
  • Click the Body tab, select raw, and choose JSON from the dropdown.
  • Enter this JSON body:
{
    "title": "The Great Gatsby (Updated Edition)"
}
  • Click Send.

You should see the book returned with the updated title but the original author still intact.

Not seeing the updated book?

  • Make sure you saved app.py after adding the new endpoint. The debug server auto-reloads on save.
  • Check that the method dropdown says PUT, not POST or GET.
  • Confirm the Body type is set to raw and JSON, not Text or Form.

Still stuck? Help me debug my PUT endpoint in Flask

Add the DELETE endpoint for removing books

The DELETE method tells the server to remove a resource permanently. Your endpoint will find the book, remove it from the list, and return a confirmation message.

  • In app.py, find the if __name__ == '__main__': line again.
  • Add the following DELETE endpoint above it (below your PUT endpoint):
@app.route('/books/<int:book_id>', methods=['DELETE'])
def delete_book(book_id):
    # Declare books as global so we can reassign the list
    global books
    # Find the book by ID
    book = next((b for b in books if b['id'] == book_id), None)
    if book is None:
        return jsonify({"error": "Book not found"}), 404
    # Remove the book by rebuilding the list without it
    books = [b for b in books if b['id'] != book_id]
    return jsonify({"message": f"Book {book_id} deleted successfully"})

Why do we need global books?

Python treats books = [...] as creating a new local variable inside the function. The global keyword tells Python you want to reassign the module-level books list, not create a new local one.

Without it, the original list would remain unchanged and the book would still appear in future GET requests.

  • Save app.py.
  • In Postman, set the method to DELETE.
  • Set the URL to http://127.0.0.1:5000/books/1.
  • Click Send.

You should see the message Book 1 deleted successfully in the response.

Still seeing the book after deletion?

  • Make sure the global books line is inside your delete_book function, before you reassign the list.
  • Check that the method is set to DELETE in Postman, not GET.

Need more help? Help me debug my DELETE endpoint

Test the full CRUD cycle in Postman

You now have all four CRUD operations wired up. Time to run through the complete lifecycle of a book to prove everything works together.

Before you run through this cycle, predict what you think will happen when you GET a book that you just deleted.

  • Send a POST request to http://127.0.0.1:5000/books with this body:
{
    "title": "Brave New World",
    "author": "Aldous Huxley"
}
  • Click Send. Note the id in the 201 response.
  • Send a GET request to http://127.0.0.1:5000/books/4 to read the new book back.
  • Send a PUT request to http://127.0.0.1:5000/books/4 with this body:
{
    "title": "Brave New World (Revised)"
}
  • Click Send. Confirm the title is updated and the author is still Aldous Huxley.
  • Send a DELETE request to http://127.0.0.1:5000/books/4.
  • Now send a GET request to http://127.0.0.1:5000/books/4.

You should see a 404 status with {"error": "Book not found"}. The book is gone. That confirms the full Create, Read, Update, Delete cycle works end to end.

What do the HTTP methods mean?

  • GET retrieves data without changing anything.
  • POST creates a new resource.
  • PUT updates an existing resource.
  • DELETE removes a resource.

These four methods map directly to the four CRUD operations that nearly every application needs.

✔️ Awesome, I've got everything!

Great. Double check you've saved app.py and your server is still running with all endpoints working.

ⓧ I'd like to double check the full code

Your app.py should contain these sections from top to bottom. Scroll up and confirm each one is present in this order:

  • The from flask import Flask, jsonify, request import line.
  • The app = Flask(__name__) line and books list with 3 books.
  • The home() function at route /.
  • The get_books() function at route /books with GET method.
  • The get_book() function at route /books/<int:book_id> with GET method.
  • The create_book() function at route /books with POST method.
  • The update_book() function at route /books/<int:book_id> with PUT method.
  • The delete_book() function at route /books/<int:book_id> with DELETE method.
  • The if __name__ == '__main__': block at the very bottom.

Your API now supports the full set of CRUD operations. You can create, read, update, and delete books through clean HTTP endpoints with proper error handling. Next up, the Secret Mission challenges you to add search and filtering so you can find specific books without scrolling through the entire collection.

Secret mission

Add Search and Filtering

Your API can list all books, but what if someone has hundreds? Real APIs let users search and filter data. In this mission, you will add query parameter support to your GET /books endpoint so users can find books by author or title.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally, so there are no ongoing costs.

Resources you used:

  • The book-api project folder on your Desktop (contains app.py and the venv virtual environment).
  • Python 3.13 installed on your machine.

Keep everything running

No action needed. Choose this if you plan to keep building on your Book API or want Python available for future projects.

  • Your book-api folder stays on your Desktop.
  • Python stays installed and available from any terminal.
  • If the Flask server is still running, you can stop it anytime with Ctrl+C in the terminal.

Pause - I'll come back to this later

Stop the Flask development server to free up your terminal. Your files stay on disk so you can pick up where you left off.

  • If your Flask server is still running, press Ctrl+C in the terminal to stop it.
  • Close the terminal in VS Code.
  • When you come back, open the book-api folder in VS Code, open a new terminal, activate your virtual environment with venv\Scripts\activate, and run python app.py to start the server again.

Delete - I don't want to use this again

Remove all project files. Follow these steps to clean up completely.

  • If your Flask server is still running, press Ctrl+C in the terminal to stop it.
  • Delete the book-api folder. On macOS/Linux, run:
rm -rf ~/Desktop/book-api
  • On Windows, run:
rmdir /s /q %USERPROFILE%\Desktop\book-api
  • To uninstall Python (optional, skip this if you want Python for other projects): open Settings, select Apps, then Installed apps. Search for Python, click the three dots next to the Python entry, and select Uninstall.

Nice Work!

Nice Work!

You just built a fully functional REST API from scratch using Python and Flask. Your Book Collection API handles real HTTP requests, responds with JSON data, and manages the full lifecycle of a resource.

You've learned how to:

  • Built a complete REST API with all four CRUD operations: Create (POST), Read (GET), Update (PUT), and Delete (DELETE).
  • Handled errors with proper HTTP status codes (200, 201, 400, 404) so your API communicates clearly when something goes wrong.
  • Tested every endpoint using Postman, sending requests and inspecting JSON responses just like professional API developers do.
  • Secret Mission: Added search and filtering with URL query parameters so users can find books by author or title.

Ready to quiz yourself?