RESTful API backend for Truth Label application. Integrates with Open Food Facts to verify sustainability claims and calculate reliability scores for food products.
This backend provides the core functionality for the Truth Label project, including product scanning, score calculation, database management, and API endpoints for the frontend application.
Developed by: Clรกudia Rodrigues
Context: MVP Project for Post-Graduate Software Engineering - PUC-Rio
- ๐ RESTful API with OpenAPI 3.0 documentation
- ๐ Open Food Facts Integration for product data
- ๐งฎ Sustainability Score Calculator (0-100 scale)
- ๐พ SQLite Database for product history
- ๐ Comment System for user feedback
- ๐ฅ User Management system
- ๐ Swagger UI for interactive API documentation
- ๐ CORS Enabled for frontend integration
- Flask 2.3.3 - Web framework
- Flask-SQLAlchemy 3.0.5 - ORM
- SQLite - Database
- Pydantic 2.5.2 - Data validation
- Flasgger 0.9.7.1 - Swagger documentation
- Flask-CORS 4.0.0 - CORS handling
- Requests 2.31.0 - HTTP client for Open Food Facts
backend/
โโโ model/ # Database models
โ โโโ __init__.py
โ โโโ product.py # Product model
โ โโโ comment.py # Comment model
โ โโโ user.py # User model
โโโ routes/ # API endpoints (Blueprints)
โ โโโ __init__.py
โ โโโ product_bp.py # Product routes
โ โโโ comment_bp.py # Comment routes
โ โโโ user_bp.py # User routes
โโโ schemas/ # Pydantic validation schemas
โ โโโ __init__.py
โ โโโ product_schemas.py
โ โโโ comment_schemas.py
โ โโโ user_schemas.py
โโโ scripts/ # Utilities
โ โโโ __init__.py
โ โโโ score_calculator.py
โโโ app.py # Flask application factory
โโโ extensions.py # SQLAlchemy instance
โโโ requirements.txt # Python dependencies
โโโ truthlable.db # SQLite database (auto-generated)
- Python 3.8+
- pip
- Virtual environment (recommended)
- Clone the repository:
git clone <backend-repo-url>
cd truth-label-backend- Create and activate virtual environment:
# Windows
python -m venv venv
venv\Scripts\activate
# Linux/Mac
python3 -m venv venv
source venv/bin/activate- Install dependencies:
pip install -r requirements.txt- Run the application:
python app.pyThe API will be available at http://127.0.0.1:5000
The database is automatically created on first run. No manual setup required.
Access the interactive Swagger documentation at:
http://127.0.0.1:5000/apidocs/
Scans a barcode, checks local database, fetches from Open Food Facts if needed.
Request Body:
{
"barcode": "7891234567890"
}Response (201 Created):
{
"message": "Product scanned and saved successfully",
"product": {
"id": 1,
"name": "Eco Green Soap",
"barcode": "7891234567890",
"score": 85.5,
"nova_group": 1,
"image_url": "https://...",
"ingredients_analysis_tags": "en:vegan,en:palm-oil-free",
"labels_tags": "en:organic,en:fair-trade",
"allergens_tags": "",
"additives_tags": "",
"date_inserted": "2025-12-20T10:30:00"
}
}Search product in local history by ID, name, or barcode.
Query Parameters:
id(integer): Product IDname(string): Product name (partial match)barcode(string): Barcode
Examples:
GET /product?barcode=7891234567890
GET /product?name=soap
GET /product?id=1
List all products in history.
Response (200 OK):
[
{
"id": 1,
"name": "Eco Green Soap",
"barcode": "7891234567890",
"score": 85.5,
...
},
...
]Update product name or barcode.
Request Body:
{
"name": "New Product Name",
"barcode": "9876543210987"
}Remove product from history.
Request Body:
{
"barcode": "7891234567890"
}Create a comment for a product.
Request Body:
{
"product_id": 1,
"author_name": "John Doe",
"text": "This product is truly sustainable!",
"n_estrela": 5
}List all comments.
Get specific comment by ID.
List all comments for a specific product.
Delete a comment.
Create a new user.
Request Body:
{
"username": "johndoe",
"email": "[email protected]"
}List all users.
Get specific user by ID.
Delete a user.
The score (0-100) is calculated based on multiple weighted criteria:
Certifications (VIP Labels):
- Organic certifications:
+15 - Fair Trade:
+15 - EU Organic:
+15 - Rainforest Alliance:
+15
Ingredient Analysis:
- Vegan:
+10 - Palm Oil Free:
+10 - Contains Palm Oil:
-20
NOVA Group (Processing Level):
- NOVA 1 (Unprocessed/Minimally processed):
+10 - NOVA 4 (Ultra-processed):
-15
Additives:
- Each additive:
-2
Starting point: 50 (neutral)
def calculate_score(off_data):
score = 50 # Base neutral score
# High Priority: Certifications
for label in labels_tags:
if label in ['en:organic', 'en:fair-trade', ...]:
score += 15
# High Priority: Ingredient Analysis
if 'en:vegan' in analysis:
score += 10
if 'en:palm-oil-free' in analysis:
score += 10
if 'en:palm-oil' in analysis:
score -= 20
# Medium Priority: NOVA Group
if nova_group == 1:
score += 10
if nova_group == 4:
score -= 15
# Medium Priority: Additives
score -= (len(additives) * 2)
# Clamp between 0-100
return max(0, min(100, score))class Product(db.Model):
id: int # Primary key
name: str # Product name
barcode: str # Unique barcode (EAN-13)
image_url: str # Product image URL
score: float # Sustainability score (0-100)
nova_group: int # Processing level (1-4)
ingredients_analysis_tags: str # Comma-separated tags
labels_tags: str # Certification tags
allergens_tags: str # Allergen tags
additives_tags: str # Additive tags
date_inserted: datetime # Scan timestamp
comments: List[Comment] # Related commentsclass Comment(db.Model):
id: int # Primary key
text: str # Comment text (max 500 chars)
author: str # Author name
n_estrela: int # Rating (0-5 stars)
date_inserted: datetime # Creation timestamp
product_id: int # Foreign key to Productclass User(db.Model):
id: int # Primary key
username: str # Unique username
email: str # Unique email
date_created: datetime # Registration timestamp1. Frontend sends POST /product/scan with barcode
2. Backend checks local database
โโ Found โ Return existing product
โโ Not found โ Continue
3. Query Open Food Facts API
4. Extract relevant data
5. Calculate sustainability score
6. Save to local database
7. Return product with score to frontend
off_url = f"https://world.openfoodfacts.net/api/v2/product/{barcode}"
response = requests.get(off_url, timeout=10)
product_data = response.json()CORS(app, resources={
r"/*": {
"origins": ["http://127.0.0.1:5500"],
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH"],
"allow_headers": ["Content-Type", "Authorization"]
}
})app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///truthlable.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False- Navigate to
http://127.0.0.1:5000/apidocs/ - Select an endpoint
- Click "Try it out"
- Fill in the parameters
- Click "Execute"
# Scan a product
curl -X POST http://127.0.0.1:5000/product/scan \
-H "Content-Type: application/json" \
-d '{"barcode": "7891234567890"}'
# Search by name
curl http://127.0.0.1:5000/product?name=soap
# List all products
curl http://127.0.0.1:5000/products-list# Delete and recreate database
rm truthlable.db
python app.py # Will auto-create new database# Change port in app.py
app.run(debug=True, port=5001) # Use different portEnsure frontend origin is listed in CORS configuration:
"origins": ["http://127.0.0.1:5500"]flasgger==0.9.7.1
Flask==2.3.3
flask-cors==4.0.0
pydantic==2.5.2
requests==2.31.0
python-dotenv==1.0.0
SQLAlchemy==2.0.15
Flask-SQLAlchemy==3.0.5
Werkzeug==2.3.7- Input validation using Pydantic schemas
- SQL injection prevention via SQLAlchemy ORM
- Error handling for external API failures
- Database transactions with rollback support
Contributions are welcome! To contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/NewFeature) - Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/NewFeature) - Open a Pull Request
This project is open-source and available under the MIT License.
- Frontend Repository: [Link to frontend repo]
Clรกudia Rodrigues
Post-Graduate Software Engineering Student - PUC-Rio
- Open Food Facts for the comprehensive API and database
- Flask community for excellent documentation
- PUC-Rio for academic support
โญ If this project was useful to you, consider giving it a star!