Aller au contenu principal

Endpoints - Challenges

Les challenges (défis / quiz) ont une API moderne paginée et des chemins legacy encore utilisés par certaines apps.

Préférez

GET /public/challenges?cityId= et POST /public/challenges/:id/complete — SDK client.public.challenges.*

API actuelle​

MéthodePathSDK
GET/public/challenges?cityId=&page=&pageSize=list(cityId?, params?)
GET/public/challenges/:idgetById(id)
GET/public/challenges/:id/seriesgetSeries(id)
POST/public/challenges/:id/completecomplete(id, { deviceId, score })
GET/public/challenges/progress/:deviceIdgetProgress(deviceId)

Body complete : { "deviceId": "…", "score": 85 }.

Séries / questions​

GET /public/series/:id
GET /public/series/:id/questions

La série n’est renvoyée que si le challenge parent est public et actif. Pas de wrapper SDK sur /public/series : passer par getSeries puis ces URLs, ou le détail getById.

Legacy (tableau non paginé)​

Les routes ci-dessous restent valides mais GET /public/challenges/:cityId est ambigu avec GET /public/challenges/:id. Pour une ville, utilisez ?cityId= ou GET /public/cities/:id/challenges.

Liste des challenges d'une ville (legacy)​

Récupère tous les challenges actifs et disponibles pour une ville spécifique.

Requête​

GET /public/challenges/:cityId

Paramètres​

  • cityId (string, requis) : Identifiant unique de la ville (UUID)

Réponse​

[
{
"id": "challenge-uuid",
"name": "Apprenti Trieur",
"description": "Apprenez les bases du tri des déchets",
"enabled": true,
"startDate": "2024-01-01T00:00:00.000Z",
"endDate": null,
"order": 1,
"requiredChallengeId": null,
"requiredChallenge": null,
"series": [
{
"id": "serie-uuid",
"name": "Série 1 - Les bases",
"description": "Première série de questions sur les bases du tri",
"order": 1,
"quizQuestions": [
{
"id": "question-uuid-1",
"material": "Bouteille en plastique",
"question": "Dans quel bac dois-je jeter cette bouteille ?",
"correctWasteTypeId": "waste-type-uuid",
"order": 1
},
{
"id": "question-uuid-2",
"material": "Journal",
"question": "Où dois-je jeter ce journal ?",
"correctWasteTypeId": "waste-type-uuid-2",
"order": 2
}
]
},
{
"id": "serie-uuid-2",
"name": "Série 2 - Le recyclage",
"description": "Questions sur le recyclage",
"order": 2,
"quizQuestions": [
{
"id": "question-uuid-3",
"material": "Brique de lait",
"question": "Cette brique de lait est-elle recyclable ?",
"correctWasteTypeId": "waste-type-uuid",
"order": 1
}
]
}
],
"badge": {
"id": "badge-uuid",
"name": "Apprenti Trieur",
"description": "Vous avez complété votre premier challenge",
"icon": "star",
"imageUrl": "https://example.com/badge.png"
}
}
]

Exemple d'utilisation​

const cityId = 'city-uuid';
const response = await fetch(`https://api.wast-o.com/public/challenges/${cityId}`);
const challenges = await response.json();

// Filtrer les challenges disponibles
const now = new Date();
const availableChallenges = challenges.filter(challenge => {
if (challenge.startDate && new Date(challenge.startDate) > now) return false;
if (challenge.endDate && new Date(challenge.endDate) < now) return false;
return challenge.enabled;
});

console.log(`Challenges disponibles: ${availableChallenges.length}`);

Compléter un challenge​

Enregistre la complétion d'un challenge par un utilisateur avec son score.

Requête​

POST /public/challenges/complete

Corps de la requête​

{
"deviceId": "device-uuid",
"challengeId": "challenge-uuid",
"score": 85
}

Paramètres​

  • deviceId (string, requis) : Identifiant unique de l'appareil/utilisateur
  • challengeId (string, requis) : Identifiant du challenge complété
  • score (number, requis) : Score obtenu (généralement entre 0 et 100)

Réponse​

{
"id": "progress-uuid",
"deviceId": "device-uuid",
"challengeId": "challenge-uuid",
"score": 85,
"completedAt": "2024-01-15T10:30:00.000Z",
"challenge": {
"id": "challenge-uuid",
"name": "Apprenti Trieur",
"description": "Apprenez les bases du tri",
"badge": {
"id": "badge-uuid",
"name": "Apprenti Trieur",
"description": "Vous avez complété votre premier challenge",
"icon": "star",
"imageUrl": "https://example.com/badge.png"
}
}
}

Exemple d'utilisation​

const deviceId = 'device-uuid';
const challengeId = 'challenge-uuid';
const score = 85;

const response = await fetch('https://api.wast-o.com/public/challenges/complete', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
deviceId,
challengeId,
score,
}),
});

const result = await response.json();
console.log(`Challenge complété ! Badge obtenu: ${result.challenge.badge.name}`);

Codes d'erreur​

  • 400 Bad Request : Paramètres invalides
  • 404 Not Found : Le challenge n'existe pas ou n'est pas disponible
  • 400 Bad Request : Le challenge n'a pas encore commencé ou est terminé

Progression d'un utilisateur​

Récupère la progression de tous les challenges complétés par un utilisateur.

Requête​

GET /public/challenges/progress/:deviceId

Paramètres​

  • deviceId (string, requis) : Identifiant unique de l'appareil/utilisateur

Réponse​

[
{
"challengeId": "challenge-uuid-1",
"challengeName": "Apprenti Trieur",
"score": 85,
"completedAt": "2024-01-15T10:30:00.000Z",
"badge": {
"id": "badge-uuid",
"name": "Apprenti Trieur",
"description": "Vous avez complété votre premier challenge",
"icon": "star",
"imageUrl": "https://example.com/badge.png"
}
},
{
"challengeId": "challenge-uuid-2",
"challengeName": "Expert du Tri",
"score": 95,
"completedAt": "2024-01-20T14:15:00.000Z",
"badge": {
"id": "badge-uuid-2",
"name": "Expert du Tri",
"description": "Vous maîtrisez le tri des déchets",
"icon": "trophy",
"imageUrl": "https://example.com/badge-expert.png"
}
}
]

Exemple d'utilisation​

const deviceId = 'device-uuid';

const response = await fetch(`https://api.wast-o.com/public/challenges/progress/${deviceId}`);
const progress = await response.json();

console.log(`Challenges complétés: ${progress.length}`);
progress.forEach(p => {
console.log(`${p.challengeName}: ${p.score}% - Badge: ${p.badge.name}`);
});

Génération d'un deviceId​

Pour suivre la progression d'un utilisateur, vous devez générer et stocker un deviceId unique. Voici un exemple d'implémentation :

function getOrCreateDeviceId() {
const STORAGE_KEY = 'wasto_device_id';
let deviceId = localStorage.getItem(STORAGE_KEY);

if (!deviceId) {
// Générer un UUID v4
deviceId = 'web_' + crypto.randomUUID();
localStorage.setItem(STORAGE_KEY, deviceId);
}

return deviceId;
}

// Utilisation
const deviceId = getOrCreateDeviceId();

Schémas de données​

Challenge​

interface Challenge {
id: string;
name: string;
description?: string;
enabled: boolean;
startDate?: string;
endDate?: string;
order: number;
requiredChallengeId?: string;
requiredChallenge?: {
id: string;
name: string;
};
series: Serie[];
badge?: Badge;
}

interface Serie {
id: string;
name: string;
description?: string;
order: number;
quizQuestions: QuizQuestion[];
}

interface QuizQuestion {
id: string;
material: string;
question: string;
correctWasteTypeId: string;
order: number;
}

interface Badge {
id: string;
name: string;
description?: string;
icon?: string;
imageUrl?: string;
}

UserProgress​

interface UserProgress {
challengeId: string;
challengeName: string;
score: number;
completedAt: string;
badge?: Badge;
}