Erreurs et limites de débit
Codes HTTP renvoyés par l'API Monsiteo (401, 402, 403, 404, 409, 422, 429...), format JSON des erreurs et limites de débit de chaque route.
L'API utilise les codes HTTP standards. Toute erreur renvoie un objet JSON avec au minimum une clé message, rédigée en français et affichable telle quelle à l'utilisateur dans la plupart des cas.
Récapitulatif#
| Code | Signification | Que faire |
|---|---|---|
200 |
Succès | |
201 |
Ressource créée (inscription, site, page, média, domaine, demande sur mesure, génération IA, duplication) | |
400 |
Signature de webhook invalide (webhook Stripe uniquement) | Vérifier le secret du webhook. |
401 |
Jeton absent, invalide ou révoqué | Se reconnecter. |
402 |
Limite de la formule atteinte | Proposer de changer de formule. |
403 |
Compte suspendu, ou ressource d'un autre compte | Ne pas réessayer. |
404 |
Ressource ou route inexistante | Vérifier l'identifiant. |
409 |
Conflit : la page a été modifiée ailleurs | Recharger la page, puis réappliquer. |
422 |
Données invalides | Corriger les champs listés dans errors. |
429 |
Trop de requêtes | Attendre Retry-After secondes. |
500 |
Erreur interne | Réessayer plus tard, nous contacter si cela persiste. |
503 |
Service non configuré (webhook Stripe) |
401 : non authentifié#
{ "message": "Unauthenticated." }
Envoyez bien Accept: application/json : sans cet en-tête, une requête non authentifiée peut être redirigée vers une page de connexion au lieu de recevoir ce 401.
402 : limite de la formule#
Renvoyé quand l'action dépasse ce que permet la formule du compte. La clé upgrade vaut toujours true : c'est le signal pour afficher une proposition de changement de formule.
{ "message": "Votre formule ne permet pas de créer un site supplémentaire.", "upgrade": true }
| Route | Message |
|---|---|
POST /sites, POST /ai/generate sans site_id |
« Votre formule ne permet pas de créer un site supplémentaire. » |
POST /sites/{site}/pages |
« Votre formule est limitée à N pages. » |
POST /sites/{site}/media |
« Espace de stockage plein pour votre formule. » |
POST /sites/{site}/domain |
« Le domaine personnalisé est inclus dans les formules payantes. » |
POST /ai/generate |
« Vous avez atteint le nombre de générations IA de votre formule ce mois-ci. » |
POST /novadesko/link |
« Novadesko est inclus dans la formule Site + Novadesko. » |
Les limites de chaque formule sont renvoyées par GET /v1/plans et dans limits de GET /v1/me :
| Gratuit | Site | Site + Novadesko | Sur mesure | |
|---|---|---|---|---|
| Prix mensuel (TTC) | 0 € / mois | 9 € / mois | 24 € / mois | Sur devis |
| Prix annuel (TTC) | Gratuit | 90 € / an | 240 € / an | Sur devis |
| Sites | 1 | 1 | 3 | Selon le projet |
| Pages par site | 5 | 30 | 100 | Selon le projet |
| Domaine personnalisé | Non | Oui | Oui | Selon le projet |
| Mention « Créé avec Monsiteo » | Affichée | Retirée | Retirée | Selon le projet |
| Générations IA par mois | 3 | 50 | 200 | Selon le projet |
| Stockage des images | 200 Mo | 2 Go | 10 Go | Selon le projet |
| Novadesko (facturation) | Non | Non | Inclus | Selon le projet |
403 : interdit#
Compte suspendu (toutes les routes protégées) :
{ "message": "Votre compte est suspendu. Contactez hello@monsiteo.com." }
Ressource appartenant à un autre compte (site, page, domaine, message, média) :
{ "message": "This action is unauthorized." }
404 : introuvable#
Identifiant inexistant ou supprimé, ou route inconnue :
{ "message": "No query results for model [App\\Models\\Site] 999" }
Ne vous fiez pas au texte exact de ce message, seulement au code 404. POST /sites/{site}/domain/verify renvoie aussi 404 si aucun domaine n'est relié au site.
409 : conflit d'édition#
PATCH /v1/pages/{page} accepte un champ updated_at (la date de dernière modification que vous connaissez). Si la page a été enregistrée depuis par un autre appareil, la mise à jour est refusée :
{ "message": "Cette page a été modifiée depuis un autre appareil. Rechargez-la.", "conflict": true }
Rechargez la page (GET /v1/pages/{page}), réappliquez vos modifications sur la version à jour, puis renvoyez-la avec le nouveau updated_at. Pour écraser volontairement la version du serveur, renvoyez la requête sans updated_at. Détails : Pages.
422 : données invalides#
Format standard de validation : message résume la première erreur et errors liste les messages par champ (notation pointée pour les champs imbriqués).
{
"message": "Cette adresse est déjà prise.",
"errors": {
"slug": ["Cette adresse est déjà prise."]
}
}
{
"message": "The theme.primary field format is invalid.",
"errors": {
"theme.primary": ["The theme.primary field format is invalid."],
"settings.business.email": ["The settings.business.email field must be a valid email address."]
}
}
Bon à savoir Les messages métier (adresse prise ou réservée, domaine invalide, page d'accueil non supprimable, identifiants incorrects...) sont rédigés en français. Les messages génériques de validation dépendent de la langue configurée sur le serveur : basez votre logique sur les noms de champs dans
errors, pas sur le texte.
Quelques routes renvoient aussi 422 sans errors : POST /billing/checkout (« Formule inconnue ou non configurée dans Stripe. ») et POST /sites/{site}/media pour un SVG invalide (« Ce fichier SVG est invalide et a été refusé. »).
429 : trop de requêtes#
{ "message": "Too Many Attempts." }
Les réponses des routes limitées portent les en-têtes X-RateLimit-Limit et X-RateLimit-Remaining. Une réponse 429 ajoute Retry-After (en secondes) et X-RateLimit-Reset (horodatage Unix). Attendez ce délai avant de réessayer, idéalement avec un délai croissant.
Limites de débit#
Les compteurs sont calculés par utilisateur connecté, ou par adresse IP pour les routes publiques.
| Route | Limite |
|---|---|
POST /auth/register, /auth/login, /auth/exchange, /auth/forgot-password |
10 par minute (compteur commun) |
GET /slugs/check |
60 par minute |
POST /agency-requests |
5 par 10 minutes |
POST /me/verification |
3 par 10 minutes |
POST /sites/{site}/media |
60 par minute |
POST /sites/{site}/domain/verify |
12 par minute |
POST /ai/generate |
5 par minute |
POST /ai/rewrite |
30 par minute |
| Autres routes | pas de limite spécifique (une protection globale peut s'appliquer côté serveur) |
500 et 503#
Une erreur 500 signale un problème de notre côté : elle est journalisée et nous sommes alertés. Réessayez après quelques instants. Le 503 n'est utilisé que par le webhook Stripe quand le secret n'est pas configuré (voir Webhooks Stripe).
Mis à jour le 26 octobre 2026