Skip to main content

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(...)

Resources