1. Tại sao API Document lại quan trọng?
Tài liệu API đóng vai trò vô cùng quan trọng trong việc giúp người dùng hiểu và sử dụng API một cách hiệu quả. Khi nhà phát triển API (API Provider) hiểu rõ từng chi tiết của API, điều này không đồng nghĩa với việc người dùng API (API Consumer) cũng dễ dàng nắm bắt được. API Consumer có thể là: CTO, business stakeholders, app developer, quality assurance engineer, IT support specialist, legal team.
Thông qua tài liệu API, nhà phát triển có thể cung cấp các thông tin cần thiết như cách API hoạt động, cách thức sử dụng, cách xử lý lỗi, và các yêu cầu bảo mật. Giống như bất kỳ sản phẩm nào, API cần có tài liệu hướng dẫn chi tiết để người dùng có thể tiếp cận và sử dụng một cách dễ dàng.
Giả sử bạn đang phát triển một ứng dụng thời tiết và muốn tích hợp với API dữ liệu thời tiết. Khi truy cập vào tài liệu API, bạn sẽ thấy hướng dẫn chi tiết về cách sử dụng API này:
- Cách lấy API Key: Bạn cần đăng ký tài khoản trên trang web cung cấp API để nhận được một API key.
- Cách gửi yêu cầu: Gửi một yêu cầu GET đến endpoint
/current-weather
, kèm theo API key và tên thành phố mà bạn muốn lấy thông tin thời tiết. - Định dạng dữ liệu trả về: Dữ liệu trả về dưới dạng JSON, với các trường như
temperature
,humidity
, vàweather description
. - Xử lý lỗi: Nếu bạn nhập sai API key, tài liệu sẽ chỉ ra rằng bạn sẽ nhận được mã lỗi
401 Unauthorized
, và bạn cần kiểm tra lại API key của mình.
2. Cấu trúc của một Tài liệu API
2.1 Title
Khi đặt tên (Title) cho API, cần tuân thủ một số quy tắc để đảm bảo tên API dễ nhận diện và nhất quán:
- Ngắn gọn và súc tích: Thay vì đặt tên là "Application Programming Interface for Managing User Data," bạn có thể đặt là "User Management API."
- Có tính mô tả: Tên API nên mô tả rõ ràng về chức năng chính của API, ví dụ: "Weather Info API."
- Tránh từ ngữ chuyên ngành hoặc viết tắt khó hiểu: Thay vì ghi "CRM API" hãy sử dụng "Customer Management API" nếu đối tượng người dùng không quen với thuật ngữ CRM.
- Bao gồm phiên bản (nếu cần thiết): Nếu API có nhiều phiên bản, hãy bao gồm thông tin phiên bản trong tiêu đề để người dùng dễ nhận biết. Ví dụ: User Management API v2.0.
2.2 Endpoint
Endpoint được định nghĩa là điểm truy cập chính vào API, nơi mà các client (như ứng dụng hoặc dịch vụ khác) sẽ gửi yêu cầu để sử dụng các chức năng mà API cung cấp.
/api/v1/users/<int:user_id>
/api/v1/users
2.3 Method
Method (phương thức) là các động từ HTTP được sử dụng để tương tác với API. Các phương thức phổ biến nhất bao gồm GET, POST, PUT, và DELETE. Mỗi phương thức đại diện cho một loại hành động khác nhau mà client có thể thực hiện trên tài nguyên (resource) của API:
- GET: Lấy thông tin từ API (không làm thay đổi dữ liệu trên server).
- POST: Gửi dữ liệu đến API để tạo mới một tài nguyên.
- PUT: Cập nhật một tài nguyên hiện có với dữ liệu mới.
- DELETE: Xóa một tài nguyên từ API.
2.4 URL Parameters
URL Parameters là các tham số được truyền qua URL dưới dạng chuỗi truy vấn (query string) để cung cấp thông tin cần thiết cho API khi gọi. Các tham số này có thể được sử dụng để lọc dữ liệu, xác định tài nguyên cụ thể, ...
Tài liệu API cần phải mô tả rõ ràng từng tham số, bao gồm:
- Tên tham số: Tên của tham số được sử dụng trong URL.
- Định dạng của tham số: Kiểu dữ liệu và định dạng mà tham số đó yêu cầu.
- Mục đích của tham số: Tại sao tham số đó cần được sử dụng.
- Bắt buộc hay tùy chọn: Xác định xem tham số có bắt buộc phải có trong yêu cầu hay không.
- Yêu cầu mã hóa URL: Nếu tham số cần được mã hóa trong URL (URL encoding), điều này cũng cần được ghi chú rõ ràng trong tài liệu.
Ví dụ: Liệt kê tham số URL cho endpoint GET /api/v1/products
name
(tùy chọn): Tên sản phẩm cần tìm kiếm. Mô tả: Sử dụng tham số này để tìm kiếm sản phẩm theo tên. Ví dụ:/api/v1/products?name=phone
.category
(tùy chọn): Danh mục sản phẩm. Mô tả: Sử dụng tham số này để lọc sản phẩm theo danh mục.Ví dụ:/api/v1/products?category=electronics
.sort
(tùy chọn): Sắp xếp kết quả. Mô tả: Sắp xếp kết quả tìm kiếm theo một trường cụ thể (ví dụ:price
,name
).Ví dụ:/api/v1/products?sort=price
.
2.5 Message Payload
Message Payload mô tả cấu trúc và định dạng của request và response giữa client và server. Dữ liệu payload được truyền trong phần thân (body) của yêu cầu HTTP, đặc biệt với các phương thức như POST, PUT, PATCH, message payload không hiển thị trong URL.
Giả sử chúng ta có một API để tạo mới tài khoản người dùng, message payload có thể được định nghĩa như sau:
Message Payload (Request)
{
"username": "johndoe",
"email": "johndoe@example.com",
"password": "securepassword123",
"age": 30,
"gender": "male"
}
Message Payload (Response)
{
"id": 101,
"username": "johndoe",
"email": "johndoe@example.com",
"created_at": "2024-08-24T12:34:56Z"
}
2.6 Header Parameters
Header Parameters đề cập đến các tham số được gửi hoặc nhận trong phần tiêu đề (header) của HTTP Request/Response. Các header này bao gồm các header chuẩn như Content-Type
, Authorization
, và các header tùy chỉnh mà API yêu cầu hoặc cung cấp.
Ví dụ: Authorization
(Bắt buộc): Token dùng để xác thực người dùng. Header này phải chứa token dưới dạng "Bearer token". Content-Type
(Bắt buộc): Xác định loại dữ liệu được gửi trong yêu cầu. Với API REST, loại dữ liệu phổ biến là application/json
.
2.7 Response Code
Response Code đề cập đến các mã trạng thái HTTP mà server trả về sau khi nhận và xử lý một yêu cầu từ client. Mỗi mã trạng thái đại diện cho kết quả của yêu cầu, có thể là thành công hoặc thất bại. Ví dụ: HTTP/1.1 200 OK
2.8 Error Codes and Responses
Error Codes and Responses trong tài liệu API cung cấp chi tiết các mã trạng thái HTTP (thường là các mã 4xx và 5xx) liên quan đến lỗi, cùng với cấu trúc thông điệp lỗi (error response payload) mà API có thể trả về.
# Error Payload
{
"error_code": "USER_NOT_FOUND",
"message": "The user with the specified ID does not exist."
}
Response Code chỉ cung cấp mã trạng thái HTTP tổng quát (ví dụ: 404 Not Found
), nhưng Error Codes and Responses cung cấp mã lỗi cụ thể (nếu có) và thông điệp lỗi rõ ràng giúp xác định chính xác nguyên nhân.
2.9 Sample Calls
Sample Calls (mẫu/ví dụ gọi API) cung cấp các ví dụ thực tế về cách gọi API, bao gồm đầy đủ các tham số cần thiết và kết quả phản hồi. Mục đích của các ví dụ này là giúp nhà phát triển dễ hình dung cấu trúc dữ liệu mà họ cần gửi và nhận khi làm việc với API. Tài liệu API nên bao gồm các ví dụ cho tất cả các định dạng dữ liệu mà API hỗ trợ, chẳng hạn như JSON và XML.
3. Hướng dẫn xây dựng API Document
4.1 Xây dựng API Document bằng Swagger
Swagger là công cụ phổ biến nhất để tạo và quản lý tài liệu API dựa trên tiêu chuẩn OpenAPI. Swagger cung cấp một công cụ tên là Swagger Editor cho phép chỉnh sửa các đặc tả API (API specifications) bằng định dạng YAML trực tiếp trong trình duyệt. Khi chỉnh sửa, Swagger Editor sẽ tự động tạo ra bản xem trước tài liệu API theo thời gian thực bằng cách sử dụng HTML, CSS, và JavaScript.
4.1.1 Cài đặt Swagger
Mở terminal hoặc command prompt và chạy lệnh sau để khởi động Swagger Editor
docker pull swaggerapi/swagger-editor
docker run -d -p 8080:8080 swaggerapi/swagger-editor
4.1.2 Viết API Document
Các bạn cũng có thể sử dụng Editor online để viết document sau đó xuất ra file yaml và import lại vào hệ thống swagger nội bộ tại https://editor.swagger.io. Dưới đây là file yaml mẫu cho API quản lý user.
openapi: 3.0.0
info:
title: User Management API
description: |
This API allows you to perform CRUD (Create, Read, Update, Delete) operations on user data.
It is designed to provide an easy way to manage user information within an application,
including user registration, profile management, and account deletion.
### Key Features:
- **User Registration**: Create new user accounts with unique usernames and secure passwords.
- **User Profiles**: Retrieve and update user profile information, including email, age, and gender.
- **User Deletion**: Safely delete user accounts from the system.
- **Authentication**: Includes bearer token authentication for secure API access.
- **Error Handling**: Comprehensive error codes and messages to guide developers in troubleshooting.
This API is ideal for applications that require user management functionality, such as e-commerce sites,
social networks, and content management systems.
version: 1.0.0
servers:
- url: http://localhost:8080/api/v1
description: Local server
paths:
/users:
get:
summary: Get list of users
operationId: getUsers
tags:
- Users
responses:
'200':
description: A list of users
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
summary: Create a new user
operationId: createUser
tags:
- Users
requestBody:
description: User object that needs to be added
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/User'
responses:
'201':
description: User created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/users/{userId}:
get:
summary: Get user by ID
operationId: getUserById
tags:
- Users
parameters:
- name: userId
in: path
required: true
description: ID of the user to retrieve
schema:
type: integer
format: int64
responses:
'200':
description: User found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
summary: Update an existing user
operationId: updateUser
tags:
- Users
parameters:
- name: userId
in: path
required: true
description: ID of the user to update
schema:
type: integer
format: int64
requestBody:
description: Updated user object
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/User'
responses:
'200':
description: User updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
summary: Delete a user by ID
operationId: deleteUser
tags:
- Users
parameters:
- name: userId
in: path
required: true
description: ID of the user to delete
schema:
type: integer
format: int64
responses:
'204':
description: User deleted successfully
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
User:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
email:
type: string
age:
type: integer
format: int32
gender:
type: string
enum:
- male
- female
- other
required:
- username
- email
- password
Error:
type: object
properties:
error_code:
type: string
message:
type: string
Bên dưới sẽ là hình ảnh hiển thị trong Swagger Editor cho API Cosumer
4.2 Xây dựng API Document bằng Postman
Postman đã được biết đến là một công cụ kiểm thử API cực kì phổ biến, gần đây họ đã bổ sung thêm nhiều tính năng giúp tạo tài liệu API theo tiêu chuẩn OpenAPI cho phép bạn có thể tự động tạo ra tài liệu API từ các mẫu sẵn có.
4.2.1 Cài đặt Postman
Mở trình duyệt và truy cập https://www.postman.com/downloads/. Chọn phiên bản phù hợp với hệ điều hành của bạn và nhấn vào nút "Download". Sau khi cài đặt xong Postman sẽ yêu cầu bạn đăng ký hoặc đăng nhập.
4.2.2 Viết API Document
Chọn File -> Import, dán phần code mẫu json bên dưới vào ô Raw Text
, Postman sẽ hỏi đưa ra 2 lựa chọn Postman Collection
hoặc OpenAPI 3
, các bạn hãy chọn chuẩn OpenAPI, chi tiết về Document các bạn có thể xem trực tiếp trong Postman ở hình bên dưới.
{
"openapi": "3.0.0",
"info": {
"title": "User Management API",
"description": "This API allows you to perform CRUD (Create, Read, Update, Delete) operations on user data. It is designed to provide an easy way to manage user information within an application, including user registration, profile management, and account deletion.",
"version": "1.0.0"
},
"servers": [
{
"url": "http://localhost:8080/api/v1",
"description": "Local server"
}
],
"paths": {
"/users": {
"get": {
"summary": "Get list of users",
"operationId": "getUsers",
"tags": ["Users"],
"responses": {
"200": {
"description": "A list of users",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
]
},
"post": {
"summary": "Create a new user",
"operationId": "createUser",
"tags": ["Users"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"responses": {
"201": {
"description": "User created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"400": {
"description": "Invalid input",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
},
"/users/{userId}": {
"get": {
"summary": "Get user by ID",
"operationId": "getUserById",
"tags": ["Users"],
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"description": "ID of the user to retrieve",
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "User found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"404": {
"description": "User not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
]
},
"put": {
"summary": "Update an existing user",
"operationId": "updateUser",
"tags": ["Users"],
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"description": "ID of the user to update",
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"responses": {
"200": {
"description": "User updated successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"400": {
"description": "Invalid input",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "User not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
]
},
"delete": {
"summary": "Delete a user by ID",
"operationId": "deleteUser",
"tags": ["Users"],
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"description": "ID of the user to delete",
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"204": {
"description": "User deleted successfully"
},
"404": {
"description": "User not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
}
},
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"email": {
"type": "string"
},
"age": {
"type": "integer",
"format": "int32"
},
"gender": {
"type": "string",
"enum": ["male", "female", "other"]
}
},
"required": ["username", "email", "password"]
},
"Error": {
"type": "object",
"properties": {
"error_code": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
},
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer"
}
}
}
}
4. Kết luận
Việc viết tài liệu API (API Documentation) đóng vai trò vô cùng quan trọng trong việc phát triển và tích hợp ứng dụng. Một tài liệu API chuẩn không chỉ giúp các nhà phát triển hiểu rõ cách sử dụng API mà còn giảm thiểu sai sót và tăng tốc độ phát triển.
Các bài viết liên quan tại Blog 200Lab:
Bài viết liên quan
Giới thiệu Kiến trúc Backend for Frontend (BFF)
Nov 16, 2024 • 10 min read
Flask là gì? Hướng dẫn tạo Ứng dụng Web với Flask
Nov 15, 2024 • 7 min read
Webhook là gì? So sánh Webhook và API
Nov 15, 2024 • 8 min read
Spring Boot là gì? Hướng dẫn Khởi tạo Project Spring Boot với Docker
Nov 14, 2024 • 6 min read
Two-Factor Authentication (2FA) là gì? Vì sao chỉ Mật khẩu thôi là chưa đủ?
Nov 13, 2024 • 7 min read
Test-Driven Development (TDD) là gì? Hướng dẫn thực hành TDD
Nov 13, 2024 • 6 min read