API Introduction
Application Programming Interface (API) in a nutshell
What is an API
API (Application Programming Interface) is a set of functions that allow you (as a developper or 'client') to use applications services. They are like special messengers that helps different computers systems talk to each other.
It defines methods and rules for how one piece of software can request and exchange data or functionality with another, without needing to know how the other system works internally 😎
An API can be distributed/served locally (only accessible by restricted scripts), or on the other hand it may be intended to be used by a larger number of actors like ours belloved LLMs providers 😇
Below an illustration from Postman that explain how APIs works by sharing data between applications, systems, and devices through a request and response cycle.
You can take a look at the excellent article from Postman : What is an API? who explain all about API history, types and benefits, great lecture !
In short, knowing how to use APIs is essential for us developers because it unlocks the ability to integrate, automate, and enhance applications without reinventing the wheel 🥷
There are 3 different types of APIs : private, public and partner (or integration).
- Private APIs: Only used within one organization, for internal use, and not accessible to outsiders 🙈
- Public APIs: Available to the public, allowing third-party developers to access data or services in exchange for payment like OpenAI GPT 😄
- Partner APIs: Used by multiple companies that collaborate on a project, with authentication mechanisms to ensure only authorized partners can use them 🤝
You can also define APIs according to their architectural paradigm, of which there are planty but the most frequently used are shown below 🥸
1. REST (Representational State of Resource)
👀 Currently the most popular API architecture for transferring data over the internet.
- Characteristic : Client-server architecture, request-response format
- Use case: Web services, web applications, mobile apps
- Key features:
- Resource-based (e.g., /users, /posts)
- Request and response formats are standard HTTP methods (GET, POST, PUT, DELETE) and JSON/XML data
- Cacheable responses
- Stateless (no session state)
Google Maps API, GitHub API
2. gRPC (Google Remote Procedure Call)
- Characteristic: High-performance RPC framework
- Use case: Microservices architecture, high-traffic web applications
- Key features:
- Bidirectional streaming and unidirectional streaming support
- Request-response format is binary-encoded message
- Supports load balancing and circuit breakers
- Optimized for performance and efficiency
YouTube API, Google Cloud APIs
3. GraphQL
- Characteristic: Query language for APIs
- Use case: Complex data queries, real-time updates, mobile apps
- Key features:
- Schema-driven (defines the structure of requests and responses)
- Queries are flexible and can be used to fetch specific data
- Supports subscription-based notifications
- Optimized for caching and performance
Facebook API, GitHub API
4. SOAP (Simple Object Access Protocol)
- Characteristic: Platform-agnostic RPC framework
- Use case: Enterprise applications, legacy systems
- Key features:
- Request-response format is XML-encoded message
- Supports multiple communication protocols (HTTP, SMTP)
- Includes WS-Security and other security features for authentication and authorization
- Can be complex to use due to its verbose nature
Microsoft Dynamics CRM API, SAP API
5. WebSocket
- Characteristic: Bi-directional communication framework
- Use case: Real-time updates, live chat applications, gaming
- Key features:
- Establishes a persistent connection between client and server
- Allows for bidirectional communication (both sending and receiving data)
- Optimized for low-latency and real-time updates
Twitter API, Video and Chat app
6. GraphQL Schema
- Characteristic: Query language for APIs with schema-driven features
- Use case: Complex data queries, real-time updates, mobile apps
- Key features:
- Supports resolvers (functions that handle queries and mutations)
- Includes type definitions, interfaces, and enumerations
- Optimized for caching and performance
Facebook API, GitHub API
7. OData (Open Data Protocol)
- Characteristic: Query language for APIs with flexible data access
- Use case: Web services, enterprise applications
- Key features:
- Supports query options and parameterization
- Includes support for sorting, filtering, and aggregating data
- Optimized for large datasets and scalability
Microsoft Dynamics CRM, SAP API
8. gSOAP (Simple Object Access Protocol for XML)
The brave good old one
- Characteristic: Platform-agnostic RPC framework with XML encoding
- Use case: Enterprise applications, legacy systems
- Key features:
- Supports multiple communication protocols (HTTP, SMTP)
- Includes WS-Security and other security features for authentication and authorization
- Can be complex to use due to its verbose nature
SAP API, Oracle API
9. OpenAPI Specification
- Characteristic: Standardized API description format
- Use case: Documentation, integration testing, automated deployments
- Key features:
- Defines the structure of APIs (endpoints, methods, parameters)
- Supports automatic code generation and documentation
- Optimized for readability and maintainability
OpenAPI Specification, Swagger UI
I know it seems a lot but you can have a simple way on how to decide which API type to use :
- Simple data retrieval: REST or GraphQL
- Complex data queries: GraphQL
- Real-time updates: WebSocket
- High-performance RPC: gRPC
- Enterprise applications: SOAP, OData, or gSOAP
- Platform-agnostic: OpenAPI Specification
Keep in mind that this is not an exhaustive list, yes there is more lol and each API type has its unique strengths and weaknesses. It's essential to evaluate your project requirements and choose the best fit for your use case 🔥
In this article we will onlmy explore REST and build a simple RESTful API with python.
RESTful APIs
A RESTful API (for Representational State Transfer) is a web API architecture that relies on the HTTP protocol and uses its methods (GET, POST, PUT, DELETE) to allow clients to communicate with servers and retrieve data generally in json
format.
As said earlier, RESTful APIs are widely used in web and mobile applications to provide a standardized and easy-to-use interface to access data. It's now a go to for a developper if you want to build software.
Here are the main concepts of the RESTful architecture:
-
HTTP Verbs: HTTP verbs (GET, POST, PUT, DELETE) are used to describe operations on resources. The GET verb is used to retrieve a resource, POST to create a new resource, PUT to update an existing resource, and DELETE to delete a resource.
-
Routes: Routes in a RESTful API are specific entry points in the API that define the available operations and accessible resources. A route is usually a URI (Uniform Resource Identifier) that uniquely identifies a resource and an HTTP method that specifies the action to be taken on that resource.
-
Representations: representations are the data formats used to represent resources, such as JSON, XML, or YAML. The most commonly used format is JSON (JavaScript Object Notation) because it is lightweight, easy to read and write.
-
HTTP Response Codes: HTTP response codes are used to indicate the result of an operation on a resource. For example, code 200 indicates that the request was processed successfully, code 201 indicates that the resource was successfully created, code 404 indicates that the resource was not found, etc.
By using these concepts, a RESTful API can provide a simple, consistent, and easy-to-use interface for accessing a server's data and services. Clients can use standard HTTP requests to access resources and interact with the server, making the RESTful API very flexible and easy to integrate into web and mobile applications.
Flask mini prototype
Flask is a famous Python library for creating web applications and RESTful APIs.
Here is an example code for creating a simple RESTful API with Flask:
from flask import Flask, jsonify, request
app = Flask(__name__)
# Define some data for our API
students = [
{
'id': 1,
'name': 'Alice',
'age': 20
},
{
'id': 2,
'name': 'Bob',
'age': 22
},
{
'id': 3,
'name': 'Charlie',
'age': 21
}
]
# Route to get all students
@app.route('/students', methods=['GET'])
def get_students():
return jsonify(students)
# Route to get a particular student
@app.route('/students/<int:id>', methods=['GET'])
def get_student(id):
student = [student for student in students if student['id'] == id]
return jsonify(student)
# Route to create a new student
@app.route('/students', methods=['POST'])
def create_student():
student = {
'id': request.json['id'],
'name': request.json['name'],
'age': request.json['age']
}
students.append(student)
return jsonify(student)
# Route to update an existing student
@app.route('/students/<int:id>', methods=['PUT'])
def update_student(id):
student = [student for student in students if student['id'] == id]
student[0]['name'] = request.json.get('name', student[0]['name'])
student[0]['age'] = request.json.get('age', student[0]['age'])
return jsonify(student[0])
# Route to delete an existing student
@app.route('/students/<int:id>', methods=['DELETE'])
def delete_student(id):
student = [student for student in students if student['id'] == id]
students.remove(student[0])
return jsonify({'result': True})
# Launch the app Flask
if __name__ == '__main__':
app.run(debug=True)
And that's all, you just have to put this code inside a python script let's call it main.py
to make him really unique and run this script (do not close the terminal who is running your script since it's the server we want to be able to call him 😅)
So yeah, that's it ! With this simple example we have created a tiny API that allows us to retrieve, create, update, and delete some students 🧑🎓
We have used the@app.route
decorators to define the different routes of our API, as well as the corresponding HTTP methods (GET, POST, PUT, DELETE). We have also used Flask's jsonify function to return JSON data from our API.
If you are not familiar with the python decorators you can take a look at python doctor - decorators
Now this is the time to test our work ! To do so we can use a tool like Postman or simply make HTTP requests using the URL of our API (for this example http://localhost:5000/students to retrieve all students).
What's next
Testing our API the right way
Now that we've created our mini API, let's learn how to test it properly! There are multiple ways to interact with your API endpoints:
Using a Web Browser
For simple GET requests, you can use your web browser. Just navigate to:
- http://localhost:5000/students
to get all students
- http://localhost:5000/students/1
to get the student with ID 1
However, browsers can only make GET requests by default, so for testing POST, PUT, and DELETE methods, we need other tools.
Using cURL
cURL is a command-line tool available on most operating systems that allows you to make HTTP requests:
# GET all students
curl http://localhost:5000/students
# GET a specific student
curl http://localhost:5000/students/1
# POST a new student
curl -X POST -H "Content-Type: application/json" -d '{"id": 4, "name": "David", "age": 23}' http://localhost:5000/students
# PUT (update) a student
curl -X PUT -H "Content-Type: application/json" -d '{"name": "Alice Cooper", "age": 25}' http://localhost:5000/students/1
# DELETE a student
curl -X DELETE http://localhost:5000/students/2
Using Postman
As we seen earlier, Postman provides a user-friendly interface for making requests and viewing responses.
- Create a new request in Postman
- Select the HTTP method (GET, POST, PUT, DELETE)
- Enter the URL (
http://localhost:5000/students
) - For POST and PUT requests, go to the "Body" tab, select "raw" and "JSON", and enter your data
- Click "Send" to execute the request
Postman also allows you to save requests in tabs like in a browser, create collections, and even automate testing with scripts 😎
Using python requests
You can also test "programmatically" with a script and use the python requests
lib to do so :
import requests
import json
# Base URL for our API
base_url = "http://localhost:5000"
# GET all students
response = requests.get(f"{base_url}/students")
print("All students:", response.json())
# GET a specific student
response = requests.get(f"{base_url}/students/1")
print("Student #1:", response.json())
# POST a new student
new_student = {"id": 4, "name": "David", "age": 23}
response = requests.post(
f"{base_url}/students",
headers={"Content-Type": "application/json"},
data=json.dumps(new_student)
)
print("Created student:", response.json())
# PUT (update) a student
updated_data = {"name": "Alice Cooper", "age": 25}
response = requests.put(
f"{base_url}/students/1",
headers={"Content-Type": "application/json"},
data=json.dumps(updated_data)
)
print("Updated student:", response.json())
# DELETE a student
response = requests.delete(f"{base_url}/students/2")
print("Delete result:", response.json())
Beyond the Basics
Once we've mastered the basics of creating and testing a simple API, there are several important concepts to explore to build production-ready APIs not just basics demo ☺️
Authentication and Authorization
In real-world applications, you'll need to protect your API from unauthorized access. Common authentication mechanisms include :
- API Keys: Simple tokens included in headers or query parameters
- JWT (JSON Web Tokens): Secure, stateless tokens that can contain user claims
- OAuth 2.0: The industry-standard protocol for authorization
- Basic Authentication: Username/password encoded in Base64 (only secure over HTTPS)
Let's take a look at a simple example adding API key authentication to our mini app :
@app.route('/students', methods=['GET'])
def get_students():
api_key = request.headers.get('X-API-Key')
if api_key != 'your_secret_api_key':
return jsonify({"error": "Unauthorized"}), 401
return jsonify(students)
Rate Limiting
To prevent abuse of your API, you might want to implement rate limiting. This restricts how many requests a client can make in a given time period like when you've abused of ChatGPT 😇
With Flask, you can use other libs like Flask-Limiter
but each framework have it's own tools :
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["100 per day", "10 per hour"]
)
@app.route('/students', methods=['GET'])
@limiter.limit("5 per minute")
def get_students():
return jsonify(students)
Input Validation
Always validate and sanitize users inputs to protect against injection attacks and ensure data integrity 🧙♂️
@app.route('/students', methods=['POST'])
def create_student():
if not request.json:
return jsonify({"error": "Request must be JSON"}), 400
if 'id' not in request.json or 'name' not in request.json or 'age' not in request.json:
return jsonify({"error": "Missing required fields"}), 400
if not isinstance(request.json['age'], int) or request.json['age'] < 0:
return jsonify({"error": "Age must be a positive integer"}), 400
# Continue with creating the student...
There is a lot of tools to do this job we wxill see this in a dedicated section 🧐
Documentation
PLEASE KEEP IN MING THAT : good API documentation is crucial. You do not want to be this kind of jean michel dev 🥹
Tools like Swagger/OpenAPI can automatically generate interactive documentation from your code. In the future section we will be working with FastAPI who have an Swagger embedded
Database Integration
Again, in a real application, you'd like to store your data in a database rather than in memory 😅
Versioning
As your API evolves, you'll need a strategy for versioning to avoid breaking clients, it can be as simple as :
# Version in URL
@app.route('/v1/students', methods=['GET'])
def get_students_v1():
# Version 1 implementation
@app.route('/v2/students', methods=['GET'])
def get_students_v2():
# Version 2 implementation
# Or version in header
@app.route('/students', methods=['GET'])
def get_students():
version = request.headers.get('Accept-Version', '1')
if version == '1':
# Version 1 implementation
elif version == '2':
# Version 2 implementation
Deploying Your API
The famous deployment step only for the braves devs 🧑🏭 Once your API is ready for prime time, you'll need to deploy it, like make it live on a certain server to be running all the time. Here are some popular options :
- Traditional Servers: Use Gunicorn or uWSGI with Nginx on VPS providers like DigitalOcean, Linode, or AWS EC2
- Containerization: Package your API with Docker and deploy to container services like Kubernetes, AWS ECS, or Google Cloud Run
- Serverless: Deploy using AWS Lambda with API Gateway, Google Cloud Functions, or Azure Functions
- PaaS: Use platforms like Heroku, Vercel, or Render for simplified deployment
For this part it's a common practice to use Docker, if you do not know about Docker for application deployment you can take a look at my articles here
Conclusion
Building APIs is an essential skill for software developers now. Here we've played a little with a mini Flask API is was great and a good way to learn the fundamentals, but there's a rich ecosystem of tools and practices to explore as you advance 🥷
But you can just remember that good APIs are :
- Well-documented
- Secure
- Performant
- Easy to use
Hope you liked this content and learned a thing or two. Happy coding 🚀