Python SDK for MONCRENEAU
The official Python SDK to integrate MONCRENEAU into your Django, Flask, FastAPI, or standard Python applications.
Installation
pip install moncreneau
Or with Poetry:
poetry add moncreneau
Configuration
Standard Python
from moncreneau import MoncreneauClient
client = MoncreneauClient('YOUR_API_KEY')
With Advanced Configuration
from moncreneau import MoncreneauClient, Configuration
config = Configuration(
api_key='YOUR_API_KEY',
base_url='https://mc-prd.duckdns.org/api/v1',
timeout=30,
max_retries=3
)
client = MoncreneauClient(config)
With Environment Variables
import os
from moncreneau import MoncreneauClient
client = MoncreneauClient(os.getenv('MONCRENEAU_API_KEY'))
.env file:
MONCRENEAU_API_KEY=YOUR_API_KEY
MONCRENEAU_BASE_URL=https://mc-prd.duckdns.org/api/v1
Usage Examples
List Departments
from moncreneau import MoncreneauClient
client = MoncreneauClient('YOUR_API_KEY')
try:
departments = client.departments.list()
for dept in departments:
print(f"ID: {dept.id} - {dept.name} ({dept.address})")
except Exception as e:
print(f"Error: {e}")
Create an Appointment
from moncreneau import MoncreneauClient
from moncreneau.exceptions import InsufficientCreditsError
client = MoncreneauClient('YOUR_API_KEY')
try:
appointment = client.appointments.create(
department_id=5,
date_time='2026-02-15T10:00:00',
name='Amadou Diallo'
)
print('✅ Appointment created!')
print(f'ID: {appointment.id}')
print(f'QR Code: {appointment.qr_code}')
print(f'Status: {appointment.status}')
except InsufficientCreditsError as e:
print(f'❌ Insufficient credits: {e}')
except Exception as e:
print(f'❌ Error: {e}')
Check Availability
from moncreneau import MoncreneauClient
client = MoncreneauClient('YOUR_API_KEY')
try:
availability = client.departments.check_availability(
department_id=5,
date_time='2026-02-15T10:00:00'
)
if availability.available:
print('✅ Slot available!')
print(f'Remaining slots: {availability.remaining_slots}')
else:
print('❌ Slot unavailable')
print(f'Reason: {availability.unavailability_reason}')
except Exception as e:
print(f'Error: {e}')
Cancel an Appointment
from moncreneau import MoncreneauClient
client = MoncreneauClient('YOUR_API_KEY')
try:
cancelled = client.appointments.cancel(123)
print('✅ Appointment cancelled')
print(f'Status: {cancelled.status}')
print('💰 1 credit refunded')
except Exception as e:
print(f'❌ Error: {e}')
Django Integration
Configuration in settings.py
# settings.py
MONCRENEAU = {
'API_KEY': os.getenv('MONCRENEAU_API_KEY'),
'BASE_URL': os.getenv('MONCRENEAU_BASE_URL', 'https://mc-prd.duckdns.org/api/v1'),
'TIMEOUT': 30,
}
Django Service
Create myapp/services/moncreneau_service.py:
from django.conf import settings
from moncreneau import MoncreneauClient, Configuration
class MoncreneauService:
def __init__(self):
config = Configuration(
api_key=settings.MONCRENEAU['API_KEY'],
base_url=settings.MONCRENEAU['BASE_URL'],
timeout=settings.MONCRENEAU['TIMEOUT']
)
self.client = MoncreneauClient(config)
def create_appointment(self, department_id: int, date_time: str, name: str):
return self.client.appointments.create(
department_id=department_id,
date_time=date_time,
name=name
)
def list_departments(self):
return self.client.departments.list()
# Singleton
moncreneau_service = MoncreneauService()
Django View
from django.http import JsonResponse
from django.views import View
from moncreneau.exceptions import InsufficientCreditsError
from .services.moncreneau_service import moncreneau_service
class CreateAppointmentView(View):
def post(self, request):
try:
data = json.loads(request.body)
appointment = moncreneau_service.create_appointment(
department_id=data['department_id'],
date_time=data['date_time'],
name=data['name']
)
return JsonResponse({
'id': appointment.id,
'status': appointment.status,
'qr_code': appointment.qr_code
}, status=201)
except InsufficientCreditsError as e:
return JsonResponse({'error': str(e)}, status=402)
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
class CheckAvailabilityView(View):
def get(self, request, department_id):
date_time = request.GET.get('dateTime')
availability = moncreneau_service.client.departments.check_availability(
department_id=department_id,
date_time=date_time
)
return JsonResponse({
'available': availability.available,
'remaining_slots': availability.remaining_slots,
'unavailability_reason': availability.unavailability_reason
})
Flask Integration
Flask Configuration
from flask import Flask
from moncreneau import MoncreneauClient
import os
app = Flask(__name__)
app.config['MONCRENEAU_API_KEY'] = os.getenv('MONCRENEAU_API_KEY')
client = MoncreneauClient(app.config['MONCRENEAU_API_KEY'])
Flask Routes
from flask import Flask, request, jsonify
from moncreneau import MoncreneauClient
from moncreneau.exceptions import InsufficientCreditsError
app = Flask(__name__)
client = MoncreneauClient(os.getenv('MONCRENEAU_API_KEY'))
@app.route('/appointments', methods=['POST'])
def create_appointment():
try:
data = request.get_json()
appointment = client.appointments.create(
department_id=data['department_id'],
date_time=data['date_time'],
name=data['name']
)
return jsonify({
'id': appointment.id,
'status': appointment.status,
'qr_code': appointment.qr_code
}), 201
except InsufficientCreditsError as e:
return jsonify({'error': str(e)}), 402
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/departments/<int:id>/availability', methods=['GET'])
def check_availability(id):
date_time = request.args.get('dateTime')
availability = client.departments.check_availability(
department_id=id,
date_time=date_time
)
return jsonify({
'available': availability.available,
'remaining_slots': availability.remaining_slots
})
if __name__ == '__main__':
app.run(debug=True)
FastAPI Integration
FastAPI Application
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from moncreneau import MoncreneauClient
from moncreneau.exceptions import InsufficientCreditsError
import os
app = FastAPI()
client = MoncreneauClient(os.getenv('MONCRENEAU_API_KEY'))
class CreateAppointmentRequest(BaseModel):
department_id: int
date_time: str
name: str
@app.post('/appointments')
async def create_appointment(request: CreateAppointmentRequest):
try:
appointment = client.appointments.create(
department_id=request.department_id,
date_time=request.date_time,
name=request.name
)
return {
'id': appointment.id,
'status': appointment.status,
'qr_code': appointment.qr_code
}
except InsufficientCreditsError as e:
raise HTTPException(status_code=402, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get('/departments/{department_id}/availability')
async def check_availability(department_id: int, dateTime: str):
availability = client.departments.check_availability(
department_id=department_id,
date_time=dateTime
)
return {
'available': availability.available,
'remaining_slots': availability.remaining_slots,
'unavailability_reason': availability.unavailability_reason
}
Async Support
The SDK supports async/await operations:
from moncreneau import AsyncMoncreneauClient
import asyncio
async def main():
client = AsyncMoncreneauClient('YOUR_API_KEY')
# All operations are async
departments = await client.departments.list()
appointment = await client.appointments.create(
department_id=5,
date_time='2026-02-15T10:00:00',
name='Amadou Diallo'
)
print(f'Appointment created: {appointment.id}')
asyncio.run(main())
Error Handling
The SDK uses typed exceptions:
from moncreneau import MoncreneauClient
from moncreneau.exceptions import (
InsufficientCreditsError,
ValidationError,
NotFoundError,
UnauthorizedError,
ApiError
)
client = MoncreneauClient('YOUR_API_KEY')
try:
appointment = client.appointments.create(data)
except InsufficientCreditsError as e:
# Not enough credits
print(f'Insufficient credits: {e}')
except ValidationError as e:
# Validation failed
print(f'Validation: {e.errors}')
except NotFoundError as e:
# Resource not found
print(f'Not found: {e}')
except UnauthorizedError as e:
# Invalid API Key
print('Invalid API Key')
except ApiError as e:
# Generic API error
print(f'API error: {e.message}')
print(f'Status: {e.status_code}')
except Exception as e:
# Generic error
print(f'Error: {e}')
Advanced Configuration
Timeout and Retry
from moncreneau import MoncreneauClient, Configuration
config = Configuration(
api_key='YOUR_API_KEY',
base_url='https://mc-prd.duckdns.org/api/v1',
timeout=30, # seconds
connect_timeout=10,
max_retries=3,
retry_delay=1.0 # seconds
)
client = MoncreneauClient(config)
Logging
import logging
from moncreneau import MoncreneauClient, Configuration
# Enable logging
logging.basicConfig(level=logging.DEBUG)
config = Configuration(
api_key='YOUR_API_KEY',
debug=True
)
client = MoncreneauClient(config)
Webhooks
Verify webhook signatures:
from moncreneau import Webhook
from flask import Flask, request
app = Flask(__name__)
webhook = Webhook(os.getenv('WEBHOOK_SECRET'))
@app.route('/webhooks/moncreneau', methods=['POST'])
def handle_webhook():
payload = request.get_data(as_text=True)
signature = request.headers.get('X-Moncreneau-Signature')
if not webhook.verify_signature(payload, signature):
return {'error': 'Invalid signature'}, 401
event = request.get_json()
print(f"Event: {event['type']}")
return {'received': True}, 200
Type Hints
The SDK is fully typed (PEP 484):
from typing import List
from moncreneau import MoncreneauClient
from moncreneau.models import Department, Appointment, SlotAvailability
client = MoncreneauClient('YOUR_API_KEY')
def list_all_departments() -> List[Department]:
return client.departments.list()
def create_new_appointment(dept_id: int, dt: str, name: str) -> Appointment:
return client.appointments.create(
department_id=dept_id,
date_time=dt,
name=name
)
def check_slot(dept_id: int, dt: str) -> SlotAvailability:
return client.departments.check_availability(
department_id=dept_id,
date_time=dt
)
Unit Tests with pytest
import pytest
from moncreneau import MoncreneauClient
from moncreneau.exceptions import InsufficientCreditsError
import os
@pytest.fixture
def client():
return MoncreneauClient(os.getenv('MONCRENEAU_API_KEY'))
def test_create_appointment(client):
appointment = client.appointments.create(
department_id=5,
date_time='2026-02-15T10:00:00',
name='Test User'
)
assert isinstance(appointment.id, int)
assert appointment.status == 'PENDING'
assert appointment.qr_code is not None
def test_insufficient_credits(client):
with pytest.raises(InsufficientCreditsError):
# Create multiple appointments to exhaust credits
client.appointments.create(...)