Python: Creating a REST API

Step-by-step guide to building a REST API with Flask in Python

👋 Welcome to the Stackhero documentation!

Stackhero provides a ready-to-use Python cloud solution designed to streamline your deployment process:

  • Deploy your application to production in seconds with a simple git push.
  • Use your own domain name, with automatic HTTPS certificate configuration for secure connections handled for you.
  • Rely on automatic backups, one-click updates, and predictable pricing, so you can focus on your code, not infrastructure management.
  • Benefit from strong performance and security on a private, dedicated infrastructure. Your environment is isolated and protected.

Save time and simplify your workflow: you can have your code running with Stackhero's Python cloud hosting in just 5 minutes.

This guide shows you how to create a simple REST API using Python and Flask. Flask is a lightweight micro-framework that makes it easy to build web applications and APIs quickly.

Before getting started, make sure you have the following tools installed:

  1. Python
  2. pip
  3. git
  4. asdf

If you need help setting up your environment, see the Development platform guide. Alternatively, you can start coding instantly with the online Code-Hero platform. Code-Hero provides an online IDE and terminal, with all essential tools pre-installed. This lets you focus on your code instead of installation and setup.

Python REST API running in Code-Hero, accessible directly from the browserPython REST API running in Code-Hero, accessible directly from the browser

Start by creating a new project directory. In this example, the project is called myRestApi:

mkdir myRestApi
cd myRestApi

Set the Python version to the latest available with asdf, and initialize a Git repository:

asdf install python latest \
  && asdf local python latest

echo "__pycache__/" >> .gitignore

git init
git add -A .
git commit -m "First commit"

You need one main dependency for this example: Flask.

Flask is designed to be simple and fast, so you can build and deploy web APIs without extra overhead. It includes built-in support for routing, templating, and HTTP request handling, which helps you move from idea to working API in minutes.

You can install Flask and python-dotenv using pip:

pip install Flask python-dotenv

We include python-dotenv to manage environment variables securely and conveniently. You will see its use in later steps.

After installing, freeze your dependencies to a requirements.txt file:

pip freeze > requirements.txt

Freezing dependencies ensures everyone uses the same package versions. This small step can save hours of troubleshooting later.

Now you are ready to write your API code.

Create a file named app.py and add this code:

import os
from dotenv import load_dotenv
from flask import Flask, jsonify, request

# Load environment variables from .env for non-production environments
if os.environ.get('ENV') != 'production':
    load_dotenv()

app = Flask(__name__)

# Example tasks data
tasks = [
    {
        'id': 1,
        'title': 'Buy groceries',
        'description': 'Milk, Cheese, Pizza, Fruits',
        'done': False
    },
    {
        'id': 2,
        'title': 'Learn Python',
        'description': 'Learn Python programming basics',
        'done': False
    }
]

@app.route('/api/tasks', methods=['GET'])
def get_tasks():
    return jsonify({'tasks': tasks})

@app.route('/api/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if not task:
        return jsonify({'error': 'Task not found'}), 404
    return jsonify({'task': task[0]})

@app.route('/api/tasks', methods=['POST'])
def create_task():
    if not request.json or 'title' not in request.json:
        return jsonify({'error': 'Title is required'}), 400
    task = {
        'id': tasks[-1]['id'] + 1,
        'title': request.json['title'],
        'description': request.json.get('description', ""),
        'done': False
    }
    tasks.append(task)
    return jsonify({'task': task}), 201

if __name__ == '__main__':
    if os.environ.get('ENV') == 'production':
        app.run()
    else:
        app.run(host='0.0.0.0', port=8080, debug=True)

You can start the server with:

python app.py

With host='0.0.0.0', your API is accessible via your browser when using Code-Hero. Visit http://<XXXXXX>.stackhero-network.com:8080/api/tasks, replacing <XXXXXX> with your Code-Hero domain.

Once the server is running, you can interact with your API using cURL. Here are some example commands:

  • Retrieve all tasks:

    curl -s http://localhost:8080/api/tasks
    # Output:
    # {
    #   "tasks": [
    #     ...
    #   ]
    # }
    
  • Retrieve a specific task (ID 2):

    curl -s http://localhost:8080/api/tasks/2
    # Output:
    # {
    #   "task": {
    #     ...
    #   }
    # }
    
  • Create a new task:

    curl -s -X POST -H "Content-Type: application/json" \
    -d '{"title": "New task", "description": "Created with cURL"}' \
    http://localhost:8080/api/tasks
    # Output:
    # {
    #   "task": {
    #     ...
    #   }
    # }
    

Tip: For cleaner output, you can pipe the result to jq. For example, curl -s http://localhost:8080/api/tasks/2 | jq makes the JSON easier to read.

Example of Python REST API using Flask, running in Stackhero Code-Hero, with the server (1) and the client using cURL (2)Example of Python REST API using Flask, running in Stackhero Code-Hero, with the server (1) and the client using cURL (2)

Environment variables help you protect secrets like database credentials or API keys. Using them keeps sensitive data out of your codebase and Git history, and makes it easy to use different settings for each environment.

To manage environment variables, you can use the python-dotenv module. If you skipped the earlier install step, you can install it now:

pip install python-dotenv
pip freeze > requirements.txt

Create a .env file at your project root and add your development environment variables:

ENV="development"
DATABASE_PASSWORD="secretPassword"
THIRD_API_PRIVATE_KEY="secretKey"

Add .env to your .gitignore so it is not committed to Git:

echo ".env" >> .gitignore

You can access these variables in Python using os.environ.get():

import os

print(os.environ.get('ENV'))

The .env file is for development only. For production or staging, you can set environment variables directly in your Stackhero dashboard under your Python service configuration.

Flask's built-in server is great for development. For production, you will want a robust WSGI server such as Gunicorn. Here is how you can prepare:

  1. Install Gunicorn:

    pip install gunicorn
    pip freeze > requirements.txt
    
  2. Start your app with Gunicorn:

    ENV=production gunicorn app:app \
      --error-logfile - \
      -b 0.0.0.0:8080
    

    Here, app:app refers to your file (app.py) and the Flask application instance (app).

  3. You can add a Makefile to switch between development and production modes easily:

    .DEFAULT_GOAL := dev
    
    # Stackhero for Python runs the "run" rule by default. We override it to run 'prod'.
    run: prod
    
    prod:
    	ENV=production gunicorn app:app \
    	  --error-logfile - \
    	  -b 0.0.0.0:8080
    
    dev:
    	python app.py
    

You can start the server in development mode with make dev (or just make), or in production mode with make prod.

Stackhero makes cloud deployment simple and secure. You can deploy your Python project using the Python cloud hosting service. Features include:

  • Deployment with a single git push
  • Automatic TLS (HTTPS) with customizable domains
  • Dedicated infrastructure for security
  • Support for HTTP/2, TLS 1.3, WebSockets, GZIP & Brotli, ETag, and both TCP/UDP port access

To deploy, follow these steps:

  1. Get your public SSH key:

    cat ~/.ssh/id_*.pub
    
  2. In the Stackhero dashboard, open your "Stackhero for Python" service and select "Configure".

  3. Paste your public key in the "SSH public keys" or "Key" field.

  4. Click "Validate" to confirm your configuration.

"Stackhero for Python" public key configuration"Stackhero for Python" public key configuration

If you do not have SSH keys yet, you can generate them with:

ssh-keygen -t ed25519

Add a Git remote to your project using the command provided in your Stackhero service (replace <XXXXXX> with your service domain):

git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git

Git remote commandGit remote command

When you are ready to deploy, push your code with:

git push stackhero main

Remember to commit your changes before deploying. In Stackhero Code-Hero, you can use the Command Palette (Ctrl+Shift+P or Cmd+Shift+P) and type Git: Commit for quick commits.

After deployment, your API is live at https://<XXXXXX>.stackhero-network.com/api/tasks. Replace <XXXXXX> with your service domain to access your Flask API.

You now have a working REST API built with Flask. With this foundation, it is straightforward to expand your application, connect to databases, or integrate with other services. Flask gives you the flexibility to grow from a simple prototype to a full-featured production API.