Know these before starting to write your REST API in Python

Sivasathivel Kandasamy
4 min readDec 29, 2021

So, What is REST API?

REST ( Representative State Transfer) a.k.a RESTful API is an application programming interface that meets the requirements and limitations of the REST architectural style.

What makes an API RESTful?

In order of an API to be considered RESTful, the following architectural constraints have to be met:

  • Client-Server Architecture: Enforces the separation of concerns and allows the components to evolve and independently
  • Statelessness: Requests are made independent of one another, and are unconnected
  • Cacheable: Streamlines Client Serve interactions and avoid stale inputs from users
  • Layered System: Client components cannot tell if they connect to a server directly or through an intermediary, which could improve scalability (ex. proxies and load balancers) and security
  • Code on Demand: Servers can send executable code to the clients, temporarily, to extend functionality
  • Uniform Interface: Simplifies and decouples architecture allowing the components to evolve independently. The constraints to be met are: 1) Requested Resources are identifiable and separate from representation; 2) The client has the ability to manipulate representations they have received; 3)Messages returned to the client has enough information to process it; 4) The clients should be able to process hyperlinks from returned resource, to identify the actions available to them.

Characteristics of a well defined API?

  • Well documented and easy to work with — Ex. Using OpenAPI specifications and documentations
  • Hard to misuse
  • Complete and Concise — Developers can make full applications from the data returned
  • Uses JSON for sending and receiving data
  • Uses Nouns for EndPoints — Verbs are already available as the methods (GET, POST, PUT, DELETE)
  • Uses Plural Nouns for collections
  • Uses Status Codes in Error Handling
  • Uses Nesting of Endpoints to show hierarchal relationships
  • Uses Filtering, Sorting, Paging, and Field selection — Actions that can be performed on a collection of a REST API
  • Uses SSL for security
  • Uses versioning of endpoints

Now, Let’s design an awesome REST API…

Now lets try to create an API that meets the expectations of the best practices

What is the API going to do?

We are going to create a simple billing app. The app:

  • For new users, will create users
  • Existing users can records transactions and obtain summaries of their transactions

Framework to create the API?

  • FastAPI
  • SqLite3
  • Uvicorn
  • SQLAlchemy

We have to create two sets of Classes, on for database connections and one for passing parameters using the API.

Liveness Check

  • This endpoint passes the status_code. I have included here for the emphasis (have not included it in other endpoints).
@app.get("/v1/liveness", status_code=200)
async def liveness():
"""
This endpoint uses versioning and Nouns
This endpoint uses GET as no information is passed from the user.
When information are passed, it is advised to use POST, as the
parameters would be in the body instead of the URL.
"""
return {"App is live"}

User Model

First, I have created a for the “User” table. SqlAlchemy uses this class to insert and retrieve data from SQLite3

class User(Base):__tablename__ = "users"user_id = Column(Integer, primary_key=True, index=True, autoincrement=True)first_name = Column(String)last_name = Column(String)email = Column(String, unique=True, index=True)

The class is pretty straight forward. The database Table, “users”, has 4 columns with ‘user_id’ set as the primary key.

The class used by the API to create this entry is given below:

class UserCreate(BaseModel):    first_name: str    last_name: str    email: str    class Config:
orm_mode = True

This would be the class used to get the input parameters to make an entry into the ‘users’ table.

Transaction Model

Similarly, I define two classes for recording transactions and get the parameters

class Transaction(Base):
__tablename__ = "transactions"
user_email = Column(String, primary_key=True, index=True)
transaction_date = Column(Date, default=current_date)
transaction_item = Column(String)
transaction_quantity = Column(String)
item_unit_cost = Column(Float)
class TransactionCreate(BaseModel):
user_email: str
transaction_date: date
transaction_item: str
transaction_quantity: int
item_unit_cost: float
class Config:
orm_mode = True

EndPoint to create users

As per the best practices, the end point:

  • uses small letters
  • the endpoint is versioned. This makes the API maintainable and extendable
@app.post("/v1/create_user", response_model=UserCreate)
async def create_user(user: UserCreate,
db: Session = Depends(get_db)):
new_user = crud.register_user(db, user=user)
return new_user

EndPoint to obtain transaction records

  • Each endpoint here does exactly one action. Making it difficult to be misused
  • The different endpoints implement filtering to obtain data from the database
@app.post("/v1/transactions_by_entry_order")
async def get_transactions_entry_order(user_email: str,
from_entry_number: int,
to_entry_number: int,
db: Session=Depends(get_db)):
transaction = crud.get_transactions_by_entry_number(db,
user_email=user_email,
from_entry_number=from_entry_number,
to_entry_number=to_entry_number)
return transaction
@app.post("/get_all_transactions")
async def get_all_transcations(user_email: str,
db: Session=Depends(get_db)):
"""
The endpoint doesn't use versioning, which will result in a lot of complications down the line during maintenance
"""
return crud.get_all_transactions(db, user_email=user_email)
@app.post("/v1/transactions_by_date")
async def get_transcations_by_date(user_email: str,
from_date:str,
to_date:str,
db: Session=Depends(get_db)):
return crud.get_transactions_by_dates(db,
user_email=user_email,
from_date=from_date,
to_date=to_date)

API Documentation & Validations

In Flask, I used to create the API specifications myself. However, with FastAPI, this is already integrated making documentations easy. Further, it also goes very well with PyDantic for data validation.

FastAPI also provides another UI for documentation and experimentation.

Github Repo

For who wants to try the entire code, please feel free to visit my git repo:

https://github.com/Sivasathivel/billing_app.git

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response