This document provides the API specification for implementing NutriTrack mobile applications (Android/iOS). The API is fully functional and ready for mobile integration.
- Production API Base URL:
https://api.nerdstips.com/v1 - Development API Base URL:
http://localhost:3001/api - Content-Type:
application/json - Authentication: JWT Bearer tokens
POST /auth/signup
{
"email": "user@example.com",
"password": "password123",
"name": "User Name"
}Response 201:
{
"user": {
"id": "user_id",
"email": "user@example.com",
"name": "User Name",
"avatar": null,
"provider": "email",
"emailVerified": false
},
"token": "jwt_token_here"
}POST /auth/login
{
"email": "user@example.com",
"password": "password123"
}Response 200: Same as signup response
GET /auth/google
- Redirects to Google OAuth consent screen
- Use WebView or system browser for OAuth flow
- Google redirects to:
https://api.nerdstips.com/v1/auth/google/callback - Backend redirects to:
https://nerdstips.com/auth/callback?token=JWT_TOKEN - Extract token from URL parameters
GET /auth/me
Headers: Authorization: Bearer <token>
Response 200:
{
"id": "user_id",
"email": "user@example.com",
"name": "User Name",
"avatar": "https://lh3.googleusercontent.com/...",
"provider": "google",
"emailVerified": true,
"preferences": {
"id": "pref_id",
"userId": "user_id",
"avoidPeriodDays": 7,
"dietaryRestrictions": [],
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z"
}
}POST /auth/logout
Headers: Authorization: Bearer <token>
Response 200:
{
"message": "Logged out successfully"
}GET /ingredients
Headers: Authorization: Bearer <token>
Response 200:
[
{
"id": "ingredient_id",
"name": "Tomato",
"category": "Vegetables",
"nutritionPer100g": {
"calories": 18,
"protein": 0.9,
"carbs": 3.9,
"fat": 0.2,
"fiber": 1.2
},
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z"
}
]POST /ingredients
Headers: Authorization: Bearer <token>
{
"name": "Ingredient Name",
"category": "Category",
"nutritionPer100g": {
"calories": 100,
"protein": 5.0,
"carbs": 20.0,
"fat": 2.0,
"fiber": 3.0
}
}PUT /ingredients/:id
Headers: Authorization: Bearer <token>
{
"name": "Updated Name",
"category": "Updated Category",
"nutritionPer100g": {
"calories": 120,
"protein": 6.0,
"carbs": 22.0,
"fat": 2.5,
"fiber": 3.5
}
}DELETE /ingredients/:id
Headers: Authorization: Bearer <token>
Response 200:
{
"message": "Ingredient deleted successfully"
}GET /dishes
Headers: Authorization: Bearer <token>
Response 200:
[
{
"id": "dish_id",
"name": "Tomato Salad",
"description": "Fresh tomato salad",
"instructions": "Mix tomatoes with dressing",
"servings": 2,
"userId": "user_id",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"ingredients": [
{
"id": "dish_ingredient_id",
"dishId": "dish_id",
"ingredientId": "ingredient_id",
"quantity": 200,
"unit": "grams",
"ingredient": {
"id": "ingredient_id",
"name": "Tomato",
"category": "Vegetables",
"nutritionPer100g": {
"calories": 18,
"protein": 0.9,
"carbs": 3.9,
"fat": 0.2,
"fiber": 1.2
}
}
}
]
}
]POST /dishes
Headers: Authorization: Bearer <token>
{
"name": "Dish Name",
"description": "Dish description",
"instructions": "Cooking instructions",
"servings": 4,
"ingredients": [
{
"ingredientId": "ingredient_id",
"quantity": 100,
"unit": "grams"
}
]
}PUT /dishes/:id
Headers: Authorization: Bearer <token>
{
"name": "Updated Dish Name",
"description": "Updated description",
"instructions": "Updated instructions",
"servings": 2,
"ingredients": [
{
"ingredientId": "ingredient_id",
"quantity": 150,
"unit": "grams"
}
]
}DELETE /dishes/:id
Headers: Authorization: Bearer <token>
Response 200:
{
"message": "Dish deleted successfully"
}POST /consumption
Headers: Authorization: Bearer <token>
{
"type": "ingredient",
"itemId": "ingredient_id",
"quantity": 100,
"unit": "grams",
"consumedAt": "2025-01-01T12:00:00.000Z"
}Or for dishes:
{
"type": "dish",
"itemId": "dish_id",
"servings": 1,
"consumedAt": "2025-01-01T12:00:00.000Z"
}GET /consumption?days=7
Headers: Authorization: Bearer <token>
Query Parameters:
days: Number of days to retrieve (default: 7)startDate: Start date in ISO formatendDate: End date in ISO format
Response 200:
[
{
"id": "consumption_id",
"userId": "user_id",
"type": "ingredient",
"ingredientId": "ingredient_id",
"dishId": null,
"quantity": 100,
"unit": "grams",
"servings": null,
"consumedAt": "2025-01-01T12:00:00.000Z",
"createdAt": "2025-01-01T12:00:00.000Z",
"ingredient": {
"id": "ingredient_id",
"name": "Tomato",
"category": "Vegetables"
}
}
]DELETE /consumption/:id
Headers: Authorization: Bearer <token>
Response 200:
{
"message": "Consumption entry deleted successfully"
}GET /recommendations/dishes
Headers: Authorization: Bearer <token>
Query Parameters:
days: Period for freshness calculation (default: 7)limit: Number of recommendations (default: 10)
Response 200:
[
{
"dish": {
"id": "dish_id",
"name": "Fresh Salad",
"description": "Healthy salad",
"servings": 2,
"ingredients": [
{
"ingredient": {
"id": "ingredient_id",
"name": "Lettuce",
"category": "Vegetables"
},
"quantity": 100,
"unit": "grams"
}
]
},
"score": 0.85,
"explanation": "Contains 85% fresh ingredients not consumed recently"
}
]401 Unauthorized:
{
"error": "Invalid token"
}400 Bad Request:
{
"error": "Invalid input data",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}500 Internal Server Error:
{
"error": "Internal server error"
}- Store JWT tokens securely (Keychain on iOS, KeyStore on Android)
- Include token in Authorization header:
Bearer <token> - Tokens expire after 7 days
- Use WebView or system browser for Google OAuth
- Handle redirect to extract token from URL
- Store token and redirect to app's main screen
- Implement retry logic for network errors
- Handle 401 errors by clearing token and redirecting to login
- Show user-friendly error messages for validation errors
- Implement offline-first approach if needed
- Cache frequently accessed data (ingredients, dishes)
- Sync consumption logs when online
- No explicit rate limiting currently implemented
- Use reasonable request intervals for real-time features
GET /health
Response 200:
{
"status": "OK",
"timestamp": "2025-01-01T12:00:00.000Z"
}- All timestamps are in ISO 8601 format
- Nutritional values are per 100g for ingredients
- Quantities can be in grams, ml, pieces, etc.
- User preferences include dietary restrictions and recommendation settings
- The API supports CORS for web applications