Facturation
Gérez votre abonnement, consultez les factures et suivez l'utilisation
MailLand utilise Stripe pour la gestion des abonnements et la facturation. Chaque espace de travail dispose de son propre abonnement avec une tarification basée sur l'utilisation ou sur un forfait. Tout membre peut consulter l'état de facturation ; seul le propriétaire de l'espace de travail peut le modifier (les appels de mutation renvoient 403 INSUFFICIENT_PERMISSIONS, et les clés API sont toujours refusées sur ces endpoints).
Statuts de paiement
paymentStatus est renvoyé sous forme de chaîne snake_case, pas d'énumération numérique :
| Statut | Description |
|---|---|
current | Abonnement actif, paiement à jour |
grace_period | Échec du paiement, période de grâce active |
overdue | Paiement en retard, fonctionnalités restreintes |
blocked | Compte bloqué pour non-paiement |
Obtenir les détails de l'abonnement
GET https://api.mail.land/v1/account/subscriptioncurl https://api.mail.land/v1/account/subscription \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"planName": "Pro",
"monthlyEmailLimit": 100000,
"rateLimitPerSecond": 10,
"pricePerMonth": 49.00,
"startDate": "2026-01-15T08:00:00Z",
"endDate": "2026-03-01T00:00:00Z",
"status": "Active",
"paymentStatus": "current",
"marketingPausedDueToPayment": false,
"sendingBlockedDueToPayment": false,
"transactionalDailyLimit": 5000,
"daysUntilBlocked": null,
"cancelAtPeriodEnd": false,
"planFamilyId": "fam_pro",
"planTierPublicId": "tier_pro_monthly",
"usage": {
"emailsSentThisMonth": 45000,
"monthlyLimit": 100000,
"percentageUsed": 45.0,
"transactionalCount": 30000,
"marketingCount": 12000,
"apiCount": 40000,
"smtpCount": 5000,
"campaignCount": 3000,
"automationCount": 2000,
"inboundForwardCount": 500
}
}Il n'y a pas de id, planId, interval, currentPeriodStart/currentPeriodEnd, ni de champs numériques imbriqués paymentStatus/validation/domaine/équipe/automatisation dans cette réponse : utilisez les noms de champs ci-dessus. paymentStatus est une chaîne snake_case : "current", "grace_period", "overdue" ou "blocked". status est en PascalCase ("Active", "Suspended", "Cancelled") : la seule exception est le repli sans abonnement, qui renvoie "active" en minuscules.
Champs d'utilisation
| Champ | Description |
|---|---|
emailsSentThisMonth | E-mails envoyés durant la période de facturation en cours |
monthlyLimit | Nombre maximum d'e-mails par période |
percentageUsed | emailsSentThisMonth en pourcentage de monthlyLimit |
transactionalCount | E-mails transactionnels envoyés |
marketingCount | E-mails marketing envoyés |
apiCount | E-mails envoyés via l'API |
smtpCount | E-mails envoyés via le relais SMTP |
campaignCount | E-mails envoyés par des campagnes |
automationCount | E-mails envoyés par des automatisations |
inboundForwardCount | E-mails envoyés par des règles de transfert entrant |
Il n'y a pas de compteurs d'utilisation pour la validation, les domaines, les membres d'équipe ou les automatisations dans cette réponse, seulement des compteurs d'envoi d'e-mails.
Quand l'utilisation des e-mails est comptée
Les destinataires comptent contre votre utilisation et votre quota (emailsSentThisMonth / monthlyLimit) au moment où l'acceptation est enregistrée de manière durable. Les destinataires rejetés ou supprimés avant l'acceptation ne comptent jamais. Un rebond, une suppression en aval, un échec de livraison ou toute autre non-livraison survenant après l'acceptation ne restaure ni ne récupère automatiquement l'utilisation ou le quota : le compte n'est pas ajusté rétroactivement. Cette section décrit uniquement la comptabilité d'utilisation ; elle n'énonce ni n'implique une tarification Stripe par e-mail ou un quelconque droit de remboursement, régis séparément par les conditions de votre abonnement.
Le quota se réinitialise à chaque période de facturation Stripe pour les plans facturés via Stripe, ou le 1er de chaque mois calendaire UTC pour les plans non facturés via Stripe (Free et plans accordés par un administrateur) : ce n'est pas toujours "par période" au sens de Stripe.
Plans et rétention
Les plans sont Free, Pro et Max. Les journaux de messages sont conservés 30 jours pour Free, 90 jours pour Pro et 180 jours pour Max.
Résumé de politique
Obtenez le statut de vérification de l'espace de travail et la politique d'envoi :
GET https://api.mail.land/v1/account/subscription/policy-summarycurl https://api.mail.land/v1/account/subscription/policy-summary \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."La réponse réelle est un objet imbriqué, pas plat (SubscriptionController.cs:137-200) :
{
"subscription": {
"planFamilyId": "fam_pro",
"planFamilyName": "Pro",
"planTierId": "tier_pro_monthly",
"monthlyQuota": 100000,
"pricePerMonth": 49.00
},
"usage": {
"usedThisMonth": 45000,
"remainingThisMonth": 55000,
"percentUsed": 45.0
},
"effectiveRates": {
"transactionalRatePerMin": 600,
"marketingRatePerMin": 300,
"isOverridden": false
},
"domainWarmup": [
{
"domainId": "h4k7m1n9w2p5x8",
"domainName": "example.com",
"currentStage": 2,
"totalStages": 5,
"todaySentCount": 350,
"dailyLimit": 500,
"progressPercent": 70.0,
"completed": false,
"bypassed": false
}
],
"alerts": [
{
"type": "warning",
"code": "QUOTA_WARNING",
"message": "You have used 80% of your monthly quota. Consider upgrading your plan.",
"actionUrl": "/billing"
}
],
"dailySendingLimit": {
"limit": 5000,
"usedToday": 1200,
"remainingToday": 3800,
"resetsAt": "2026-02-18T00:00:00Z"
},
"verification": {
"level": 2,
"levelName": "SenderVerified",
"limits": {},
"progress": {},
"nextSteps": []
}
}| Champ | Description |
|---|---|
subscription | Famille du plan, palier et quota/prix mensuel |
usage | E-mails utilisés, restants et le pourcentage utilisé ce mois-ci |
effectiveRates | Taux d'envoi effectifs par minute et s'ils sont surchargés |
domainWarmup | Progression du préchauffage par domaine, une entrée par domaine en préchauffage |
alerts | Alertes actives pour cet espace de travail (quota, limite journalière, etc.) |
dailySendingLimit | Limite d'envoi journalière et marge restante, le cas échéant |
verification | Niveau de vérification actuel, ses limites, sa progression et les prochaines étapes |
Créer une session de paiement
Démarrez une session Stripe Checkout pour s'abonner ou mettre à niveau :
POST https://api.mail.land/v1/account/billing/checkout{
"planTierId": "tier_pro_monthly",
"locale": "en",
"businessAttested": true,
"businessAttestationKey": "business-use-v3-button"
}| Champ | Type | Requis | Description |
|---|---|---|---|
planTierId | string | Oui | Id public du palier de forfait |
locale | string | Non | Langue de la page de paiement hébergée |
businessAttested | boolean | Oui | true confirme que vous achetez MailLand à des fins professionnelles (y compris en tant que freelance, entrepreneur individuel ou pour votre propre site web). Le tableau de bord l'envoie via le bouton de paiement : son libellé indique « Pay for business use » et une note d'une ligne en dessous précise ce que le clic confirme |
businessAttestationKey | string | Oui | La version du libellé à laquelle la confirmation se rapporte ; actuellement business-use-v3-button (business-use-v1, l'ancien libellé, est toujours accepté) |
Une requête sans businessAttested: true et sans businessAttestationKey accepté est refusée avec 400 BUSINESS_ATTESTATION_REQUIRED avant tout débit. MailLand enregistre qui a confirmé, quand, avec quel libellé (la clé que vous avez envoyée) et dans quelle langue. Dans Stripe Checkout, vous pouvez saisir un numéro de TVA ou d'identification fiscale ; c'est facultatif. Les prix s'entendent hors TVA et MailLand ne facture pas la TVA ; un numéro de TVA de l'UE vérifié, hors Royaume-Uni, ajoute la mention d'autoliquidation à vos factures.
Il n'y a pas de champ successUrl ni cancelUrl : les URLs de succès/annulation ne sont pas fournies par l'appelant.
curl -X POST https://api.mail.land/v1/account/billing/checkout \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "planTierId": "tier_pro_monthly", "locale": "en", "businessAttested": true, "businessAttestationKey": "business-use-v3-button" }'{
"upgraded": false,
"sessionId": "cs_live_abc123...",
"url": "https://checkout.stripe.com/c/pay/cs_live_abc123..."
}Redirigez l'utilisateur vers url pour finaliser le paiement sur la page de paiement hébergée par Stripe. Si l'espace de travail dispose déjà d'un abonnement actif, le plan est modifié sur place plutôt que d'ouvrir un nouveau paiement : la réponse est { "upgraded": true } sans sessionId/url, et il n'y a pas de redirection. Ne redirigez que lorsque url est présent.
Portail de facturation
Ouvrez le portail client Stripe pour la gestion en libre-service (mettre à jour le mode de paiement, annuler, consulter les factures) :
POST https://api.mail.land/v1/account/billing/portal{
"locale": "en"
}locale est facultatif.
curl -X POST https://api.mail.land/v1/account/billing/portal \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "locale": "en" }'{
"url": "https://billing.stripe.com/p/session/abc123..."
}Redirigez l'utilisateur vers url pour accéder au portail Stripe.
Lister les factures
GET https://api.mail.land/v1/account/billing/invoices| Paramètre | Type | Défaut | Description |
|---|---|---|---|
limit | int | 20 | Nombre de factures à retourner |
cursor | string | - | Curseur opaque provenant du nextCursor d'une réponse précédente |
curl https://api.mail.land/v1/account/billing/invoices \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{
"publicId": "inv_abc123",
"invoiceNumber": "INV-2026-0015",
"stripeInvoiceId": "in_1AbCdEfGhIjKlMn",
"status": "Paid",
"amountDue": 4900,
"amountPaid": 4900,
"currency": "eur",
"periodStart": "2026-01-01T00:00:00Z",
"periodEnd": "2026-02-01T00:00:00Z",
"paidAt": "2026-01-01T00:05:00Z",
"hostedInvoiceUrl": "https://pay.stripe.com/invoice/inv_abc123",
"invoicePdfUrl": "https://pay.stripe.com/invoice/inv_abc123/pdf",
"createdAt": "2026-01-01T00:00:00Z"
},
{
"publicId": "inv_def456",
"invoiceNumber": "INV-2026-0014",
"stripeInvoiceId": "in_2BcDeFgHiJkLmNo",
"status": "Paid",
"amountDue": 4900,
"amountPaid": 4900,
"currency": "eur",
"periodStart": "2025-12-01T00:00:00Z",
"periodEnd": "2026-01-01T00:00:00Z",
"paidAt": "2025-12-01T00:05:00Z",
"hostedInvoiceUrl": "https://pay.stripe.com/invoice/inv_def456",
"invoicePdfUrl": "https://pay.stripe.com/invoice/inv_def456/pdf",
"createdAt": "2025-12-01T00:00:00Z"
}
],
"nextCursor": null,
"hasMore": false
}Il s'agit d'une réponse paginée par curseur, pas { "invoices": [...] } : renvoyez nextCursor comme paramètre cursor pour obtenir la page suivante, et arrêtez-vous lorsque hasMore vaut false. La taille de page par défaut est 20, pas 10 ; les noms de champs sont invoiceNumber, amountDue, amountPaid, hostedInvoiceUrl et invoicePdfUrl (pas number, amount, invoiceUrl, invoicePdf).
Les montants des factures sont exprimés dans la plus petite unité de la currency de la facture (centimes pour EUR). Divisez par 100 pour l'affichage. Les prix des forfaits sont en euros (EUR), hors TVA.
Réponses d'erreur
| Statut | Code | Description |
|---|---|---|
400 | VALIDATION_FAILED | Corps de requête invalide |
400 | INVALID_REQUEST | Le palier de plan existe mais n'est pas synchronisé avec Stripe |
403 | INSUFFICIENT_PERMISSIONS | Seul le propriétaire de l'espace de travail peut effectuer cette mutation (la lecture de facturation est ouverte à tout membre) |
404 | RESOURCE_NOT_FOUND | Palier de plan inconnu ou inactif |
502 | STRIPE_ERROR | La requête Stripe a échoué |
Autres Endpoints de Facturation
Également disponibles, non détaillés ci-dessus : POST /v1/account/billing/cancel, POST /v1/account/billing/reactivate, et l'endpoint public GET /public/plans/catalog.
Étapes suivantes
- Espaces de travail : gérer les paramètres de l'espace de travail
- Gestion d'équipe : gérer les membres de l'équipe
- Limites de débit : comprendre les limites de débit de l'API