MailLandDocs
Compte

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 :

StatutDescription
currentAbonnement actif, paiement à jour
grace_periodÉchec du paiement, période de grâce active
overduePaiement en retard, fonctionnalités restreintes
blockedCompte bloqué pour non-paiement

Obtenir les détails de l'abonnement

GET https://api.mail.land/v1/account/subscription
Get subscription details
curl https://api.mail.land/v1/account/subscription \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Subscription response
{
  "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

ChampDescription
emailsSentThisMonthE-mails envoyés durant la période de facturation en cours
monthlyLimitNombre maximum d'e-mails par période
percentageUsedemailsSentThisMonth en pourcentage de monthlyLimit
transactionalCountE-mails transactionnels envoyés
marketingCountE-mails marketing envoyés
apiCountE-mails envoyés via l'API
smtpCountE-mails envoyés via le relais SMTP
campaignCountE-mails envoyés par des campagnes
automationCountE-mails envoyés par des automatisations
inboundForwardCountE-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-summary
Get policy summary
curl 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) :

Policy summary response
{
  "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": []
  }
}
ChampDescription
subscriptionFamille du plan, palier et quota/prix mensuel
usageE-mails utilisés, restants et le pourcentage utilisé ce mois-ci
effectiveRatesTaux d'envoi effectifs par minute et s'ils sont surchargés
domainWarmupProgression du préchauffage par domaine, une entrée par domaine en préchauffage
alertsAlertes actives pour cet espace de travail (quota, limite journalière, etc.)
dailySendingLimitLimite d'envoi journalière et marge restante, le cas échéant
verificationNiveau 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
Checkout request
{
  "planTierId": "tier_pro_monthly",
  "locale": "en",
  "businessAttested": true,
  "businessAttestationKey": "business-use-v3-button"
}
ChampTypeRequisDescription
planTierIdstringOuiId public du palier de forfait
localestringNonLangue de la page de paiement hébergée
businessAttestedbooleanOuitrue 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
businessAttestationKeystringOuiLa 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.

Create checkout session
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" }'
Checkout response
{
  "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
Portal request
{
  "locale": "en"
}

locale est facultatif.

Open billing portal
curl -X POST https://api.mail.land/v1/account/billing/portal \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{ "locale": "en" }'
Portal response
{
  "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ètreTypeDéfautDescription
limitint20Nombre de factures à retourner
cursorstring-Curseur opaque provenant du nextCursor d'une réponse précédente
List invoices
curl https://api.mail.land/v1/account/billing/invoices \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Invoices response
{
  "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

StatutCodeDescription
400VALIDATION_FAILEDCorps de requête invalide
400INVALID_REQUESTLe palier de plan existe mais n'est pas synchronisé avec Stripe
403INSUFFICIENT_PERMISSIONSSeul le propriétaire de l'espace de travail peut effectuer cette mutation (la lecture de facturation est ouverte à tout membre)
404RESOURCE_NOT_FOUNDPalier de plan inconnu ou inactif
502STRIPE_ERRORLa 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

Sur cette page