Mealie Client
An unofficial Python SDK for Mealie - a self-hosted recipe manager and meal planner with a RestAPI backend.
🚀 Features
- Asynchronous API Client: Built with
httpxfor high-performance async operations - Type Safety: Full type hints with
pydanticmodels for all API responses - Core Endpoints Supported: Recipes, Users, Groups, Meal Plans, and Shopping Lists
- Authentication: Secure token-based authentication and username/password login
- Recipe Management: Full CRUD operations, search, filtering, and image management
- Meal Planning: Create and manage meal plans with date filtering
- Shopping Lists: Complete shopping list and item management
- Error Handling: Comprehensive error handling with custom exceptions
- Modern Python: Support for Python 3.8+ with modern async/await patterns
📈 Current API Coverage
This SDK currently covers the following Mealie API endpoints:
✅ Recipes - Create, read, update, delete, search, image upload, import from URL
✅ Users - User management and current user info
✅ Groups - Basic group operations
✅ Meal Plans - Meal planning with date filtering
✅ Shopping Lists - Shopping lists and item management
✅ Units - Unit management
✅ Foods - Food management
✅ Households - Household management
🔄 Planned for Future Releases:
- Categories, Tags, and Tools endpoints
- Recipe Extras (custom metadata)
- Webhooks and Event Subscriptions
- Timeline Events
- Advanced search features
📦 Installation
Using pip
pip install mealie-client
Using PDM (recommended for development)
pdm add mealie-client
Using Poetry
poetry add mealie-client
🏁 Quick Start
Basic Usage
import asyncio
from mealie_client import MealieClient
async def main():
# Initialize the client
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-api-token"
) as client:
# Get all recipes
recipes = await client.recipes.get_all()
print(f"Found {len(recipes)} recipes")
# Get a specific recipe
recipe = await client.recipes.get("recipe-slug-or-id")
if recipe:
print(f"Recipe: {recipe.name}")
print(f"Description: {recipe.description}")
# Create a new recipe
new_recipe = await client.recipes.create({
"name": "Test Recipe",
"description": "A test recipe created via SDK",
"recipe_ingredient": [
{"note": "2 cups flour"},
{"note": "1 cup sugar"}
],
"recipe_instructions": [
{"text": "Mix flour and sugar"},
{"text": "Bake at 350°F for 30 minutes"}
]
})
print(f"Created recipe: {new_recipe.name}")
# Run the async function
asyncio.run(main())
Authentication
The SDK supports both API token and username/password authentication:
API Token Authentication (Recommended)
from mealie_client import MealieClient
# Using API token
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-long-lived-api-token"
) as client:
recipes = await client.recipes.get_all()
Username/Password Authentication
from mealie_client import MealieClient
# Using username/password
async with MealieClient(
base_url="https://your-mealie-instance.com",
username="your_username",
password="your_password"
) as client:
recipes = await client.recipes.get_all()
Environment Variables
# Set environment variables
# MEALIE_USERNAME=your_username
# MEALIE_PASSWORD=your_password
# MEALIE_API_TOKEN=your_api_token
from mealie_client import MealieClient
client = MealieClient.from_env("https://your-mealie-instance.com")
📖 Usage Examples
Recipe Management
from mealie_client import MealieClient
async def recipe_operations():
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-api-token"
) as client:
# Search recipes with filters
recipes = await client.recipes.get_all(
search="pasta",
categories=["Italian"],
tags=["quick"],
per_page=20,
order_by="created_at",
order_direction="desc"
)
# Get recipe details
recipe = await client.recipes.get("pasta-carbonara")
# Update a recipe
updated_recipe = await client.recipes.update("pasta-carbonara", {
"description": "Updated description",
"prep_time": "PT15M" # 15 minutes in ISO format
})
# Upload recipe image
with open("recipe-image.jpg", "rb") as image_file:
await client.recipes.upload_image("pasta-carbonara", image_file)
# Import recipe from URL
imported_recipe = await client.recipes.import_from_url(
"https://example.com/recipe"
)
# Delete a recipe
await client.recipes.delete("old-recipe-slug")
Meal Planning
from datetime import date, timedelta
async def meal_planning():
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-api-token"
) as client:
# Get current meal plans
today = date.today()
meal_plans = await client.meal_plans.get_all(
start_date=today,
end_date=today + timedelta(days=7)
)
# Create a meal plan
meal_plan = await client.meal_plans.create({
"date": today.isoformat(),
"entry_type": "dinner",
"title": "Italian Night",
"recipe_id": "pasta-carbonara-id"
})
# Update meal plan
await client.meal_plans.update(meal_plan.id, {
"title": "Updated Italian Night"
})
Shopping Lists
async def shopping_operations():
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-api-token"
) as client:
# Get all shopping lists
shopping_lists = await client.shopping_lists.get_all()
# Create a shopping list
new_list = await client.shopping_lists.create({
"name": "Weekly Groceries",
"list_items": [
{"note": "2 lbs chicken breast"},
{"note": "1 dozen eggs"},
{"note": "Fresh vegetables"}
]
})
# Add items to existing list
await client.shopping_lists.add_item(new_list.id, {
"note": "Milk - 2% gallon"
})
# Update an item
await client.shopping_lists.update_item(
new_list.id,
item_id="item-id",
{"checked": True}
)
User and Group Management
async def user_management():
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-admin-api-token" # Admin privileges required
) as client:
# Get current user info
current_user = await client.users.get_current()
print(f"Logged in as: {current_user.username}")
# Get all users (admin only)
users = await client.users.get_all()
# Create a new user (admin only)
new_user = await client.users.create({
"username": "newuser",
"email": "newuser@example.com",
"password": "secure-password",
"full_name": "New User"
})
# Get groups
groups = await client.groups.get_all()
Error Handling
from mealie_client import MealieClient
from mealie_client.exceptions import (
MealieAPIError,
AuthenticationError,
NotFoundError,
ValidationError
)
async def error_handling_example():
async with MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-api-token"
) as client:
try:
recipe = await client.recipes.get("non-existent-recipe")
except NotFoundError:
print("Recipe not found")
except AuthenticationError:
print("Invalid authentication credentials")
except ValidationError as e:
print(f"Validation error: {e.validation_errors}")
except MealieAPIError as e:
print(f"API Error: {e.message} (Status: {e.status_code})")
🛠️ Development
Prerequisites
- Python 3.8+
- PDM (Python Dependency Manager)
Setup Development Environment
-
Clone the repository:
git clone https://github.com/yourusername/mealie-client.git cd mealie-client
-
Install dependencies:
pdm install -G dev
-
Set up pre-commit hooks:
pdm run pre-commit install
Running Tests
# Run all tests
pdm run test
# Run unit tests only
pdm run pytest tests/unit
# Run integration tests only
pdm run pytest tests/integration
# Run with coverage
pdm run pytest --cov=src/mealie_client
Code Quality
# Run linting
pdm run ruff check src tests
# Format code
pdm run black src tests
# Type checking
pdm run mypy src
🔧 Configuration
Environment Variables
export MEALIE_BASE_URL="https://your-mealie-instance.com"
export MEALIE_API_TOKEN="your-api-token"
# OR
export MEALIE_USERNAME="your-username"
export MEALIE_PASSWORD="your-password"
Client Configuration
from mealie_client import MealieClient
client = MealieClient(
base_url="https://your-mealie-instance.com",
api_token="your-api-token",
timeout=30.0, # Request timeout in seconds
max_retries=3, # Number of retry attempts
retry_delay=1.0, # Delay between retries
)
📚 API Reference
Core Classes
MealieClient: Main client class for interacting with Mealie APIRecipesManager: Handles all recipe-related operationsMealPlansManager: Manages meal planning functionalityShoppingListsManager: Shopping list operationsUsersManager: User managementGroupsManager: Group managementUnitsManager: Unit managementFoodsManager: Food managementHouseholdsManager: Household management
Available Models
The SDK includes Pydantic models for all supported data structures:
Recipe,RecipeCreateRequest,RecipeUpdateRequest,RecipeSummaryMealPlan,MealPlanCreateRequest,MealPlanUpdateRequestShoppingList,ShoppingListItem,ShoppingListCreateRequestUser,UserCreateRequest,UserUpdateRequestGroup,GroupSummaryUnit,UnitCreateRequest,UnitUpdateRequest,UnitSummaryFood,FoodCreateRequest,FoodUpdateRequest,FoodSummaryHousehold,HouseholdSummary
🎯 Roadmap
Version 0.1.0 (Current)
- Recipes management endpoint
- Users management endpoint
- Groups management endpoint
- Meal plans management endpoint
- Units management endpoint
- Foods management endpoint
- Households management endpoint
- Tags management endpoint
Version 1.0.0 (Planned)
- Shopping lists management endpoint
- Categories, and Tools endpoints
- Recipe search improvements
- Better error messages
Version 1.1.0 (Planned)
- Recipe Extras support
- Webhooks management
- Timeline Events
- Advanced filtering options
Version 2.0.0 (Future)
- Bulk operations
- Enhanced meal plan features
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Workflow
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes and add tests
- Ensure all tests pass (
pdm run test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Mealie - The amazing self-hosted recipe manager
- httpx - For the excellent async HTTP client
- Pydantic - For robust data validation
📞 Support
- Issues: GitHub Issues
Disclaimer: This is an unofficial SDK and is not affiliated with or endorsed by the Mealie project.
Metadata
Release files for mealie-client 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mealie_client-0.1.3.tar.gz | 122.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mealie_client-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 176.6 kB
Release files / mealie_client-0.1.3.tar.gz
| Download URL | mealie_client-0.1.3.tar.gz |
|---|---|
| Size | 122.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ad50094d05b2d49f144348e1afb2b70ae744a04089aa239bc33d6882b16cf6e
|
|
BLAKE2b-256 checksum How to use checksums |
82704022c6a95d2f43d0dc8d7a42a10e552509ed9700ffc85d5af601afceaaaf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.11
|
Release files / mealie_client-0.1.3-py3-none-any.whl
| Download URL | mealie_client-0.1.3-py3-none-any.whl |
|---|---|
| Size | 54.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fe4d3ab5d85aaabe8c1c05ea5b67009f99596a2fa62feb4f400db9b6b0b608f1
|
|
BLAKE2b-256 checksum How to use checksums |
9534c43d15a70e665b82e5e591554db155820e5448a52d20424139c64b53d59a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.11
|