Facturación
Administre su suscripción, vea facturas y monitoree el uso
MailLand utiliza Stripe para la gestión de suscripciones y facturación. Cada espacio de trabajo tiene su propia suscripción con precios basados en uso o en plan. Cualquier miembro puede leer el estado de facturación; solo el Owner del espacio de trabajo puede modificarlo (las llamadas de mutación devuelven 403 INSUFFICIENT_PERMISSIONS, y las claves API siempre son rechazadas en esos endpoints).
Estados de Pago
paymentStatus se devuelve como una cadena snake_case, no como un enum numérico:
| Estado | Descripción |
|---|---|
current | Suscripción activa, pago al día |
grace_period | Pago fallido, período de gracia activo |
overdue | Pago vencido, funciones restringidas |
blocked | Cuenta bloqueada por falta de pago |
Obtener Detalles de Suscripción
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
}
}No hay id, planId, interval, currentPeriodStart/currentPeriodEnd, ni campos numéricos anidados de paymentStatus/validación/dominio/equipo/automatización en esta respuesta: use los nombres de campo anteriores. paymentStatus es una cadena snake_case: "current", "grace_period", "overdue" o "blocked". status está en PascalCase ("Active", "Suspended", "Cancelled"): la única excepción es el resultado sin suscripción, que devuelve "active" en minúsculas.
Campos de Uso
| Campo | Descripción |
|---|---|
emailsSentThisMonth | Correos enviados en el período de facturación actual |
monthlyLimit | Máximo de correos por período |
percentageUsed | emailsSentThisMonth como porcentaje de monthlyLimit |
transactionalCount | Correos transaccionales enviados |
marketingCount | Correos de marketing enviados |
apiCount | Correos enviados vía API |
smtpCount | Correos enviados vía relé SMTP |
campaignCount | Correos enviados por campañas |
automationCount | Correos enviados por automatizaciones |
inboundForwardCount | Correos enviados por reglas de reenvío de entrada |
No hay contadores de uso de validación, dominio, miembros del equipo o automatización en esta respuesta: solo contadores de envío de correo.
Cuándo se cuenta el uso de correo
Los destinatarios cuentan contra su uso y cuota (emailsSentThisMonth / monthlyLimit) en el momento en que la aceptación se registra de forma duradera. Los destinatarios rechazados o suprimidos antes de la aceptación nunca cuentan. Un rebote, una supresión posterior, un fallo de entrega u otra no entrega que ocurra después de la aceptación no restaura ni recupera automáticamente el uso o la cuota: el conteo no se ajusta retroactivamente. Esta sección describe solo la contabilidad de uso; no establece ni implica precios de Stripe por correo ni ningún derecho de reembolso, que se rigen por separado por los términos de su suscripción.
La cuota se restablece en cada período de facturación de Stripe para los planes facturados a través de Stripe, o el día 1 de cada mes calendario UTC para los planes no facturados a través de Stripe (Free y planes otorgados por el administrador): no siempre es "por período" en el sentido de Stripe.
Planes y retención
Los planes son Free, Pro y Max. Los registros de mensajes se conservan 30 días en Free, 90 días en Pro y 180 días en Max.
Resumen de Política
Obtenga el estado de verificación del espacio de trabajo y la política de envío:
GET https://api.mail.land/v1/account/subscription/policy-summarycurl https://api.mail.land/v1/account/subscription/policy-summary \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."La respuesta real es un objeto anidado, no plano (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": []
}
}| Campo | Descripción |
|---|---|
subscription | Familia del plan, nivel y cuota/precio mensual |
usage | Correos usados, restantes y el porcentaje usado este mes |
effectiveRates | Tasas de envío efectivas por minuto y si están sobrescritas |
domainWarmup | Progreso de calentamiento por dominio, una entrada por dominio en calentamiento |
alerts | Alertas activas para este espacio de trabajo (cuota, límite diario y similares) |
dailySendingLimit | Límite de envío diario y margen restante, cuando aplica |
verification | Nivel de verificación actual, sus límites, progreso y próximos pasos |
Crear Sesión de Pago
Inicie una sesión de Stripe Checkout para suscribirse o actualizar su plan:
POST https://api.mail.land/v1/account/billing/checkout{
"planTierId": "tier_pro_monthly",
"locale": "en",
"businessAttested": true,
"businessAttestationKey": "business-use-v3-button"
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
planTierId | string | Sí | Id público del nivel de plan |
locale | string | No | Idioma para la página de pago alojada |
businessAttested | boolean | Sí | true confirma que compra MailLand para uso empresarial o profesional (incluso como autónomo, empresario individual o para su propio sitio web). El panel lo envía en el botón de pago: su etiqueta dice «Pay for business use» y una nota de una línea debajo indica qué confirma el clic |
businessAttestationKey | string | Sí | La versión del texto a la que se refiere la confirmación; actualmente business-use-v3-button (business-use-v1, el texto anterior, se sigue aceptando) |
Una solicitud sin businessAttested: true y sin un businessAttestationKey aceptado se rechaza con 400 BUSINESS_ATTESTATION_REQUIRED antes de cobrar nada. MailLand guarda quién confirmó, cuándo, con qué texto (la clave que usted envió) y en qué idioma. En Stripe Checkout puede introducir un identificador fiscal; es opcional. Los precios no incluyen IVA y MailLand no cobra IVA; un NIF-IVA de la UE verificado, fuera del Reino Unido, añade la nota de inversión del sujeto pasivo a sus facturas.
No hay campo successUrl ni cancelUrl: las URLs de éxito/cancelación no son proporcionadas por quien llama.
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..."
}Redirija al usuario a la url para completar el pago en la página de pago alojada por Stripe. Si el espacio de trabajo ya tiene una suscripción activa, el plan se cambia en el mismo lugar en lugar de abrir un nuevo checkout: la respuesta es { "upgraded": true } sin sessionId/url, y no hay redirección. Solo redirija cuando url esté presente.
Portal de Facturación
Abra el Portal del Cliente de Stripe para la gestión de autoservicio (actualizar método de pago, cancelar, ver facturas):
POST https://api.mail.land/v1/account/billing/portal{
"locale": "en"
}locale es opcional.
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..."
}Redirija al usuario a la url para acceder al portal de Stripe.
Listar Facturas
GET https://api.mail.land/v1/account/billing/invoices| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
limit | int | 20 | Número de facturas a devolver |
cursor | string | - | Cursor opaco del nextCursor de una respuesta anterior |
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
}Esta es una respuesta paginada por cursor, no { "invoices": [...] }: pase nextCursor de vuelta como el parámetro cursor para obtener la siguiente página, y deténgase cuando hasMore sea false. El tamaño de página predeterminado es 20, no 10; los nombres de campo son invoiceNumber, amountDue, amountPaid, hostedInvoiceUrl e invoicePdfUrl (no number, amount, invoiceUrl, invoicePdf).
Los montos de las facturas están en la unidad más pequeña de la currency de la factura (céntimos para EUR). Divida entre 100 para mostrarlos. Los precios de los planes están en euros (EUR) y no incluyen IVA.
Respuestas de Error
| Estado | Código | Descripción |
|---|---|---|
400 | VALIDATION_FAILED | Cuerpo de solicitud inválido |
400 | INVALID_REQUEST | El nivel de plan existe pero no está sincronizado con Stripe |
403 | INSUFFICIENT_PERMISSIONS | Solo el Owner del espacio de trabajo puede realizar esta mutación (la lectura de facturación está abierta a cualquier miembro) |
404 | RESOURCE_NOT_FOUND | Nivel de plan desconocido o inactivo |
502 | STRIPE_ERROR | La solicitud a Stripe falló |
Otros Endpoints de Facturación
También disponibles, no detallados arriba: POST /v1/account/billing/cancel, POST /v1/account/billing/reactivate, y el endpoint público GET /public/plans/catalog.
Pasos Siguientes
- Espacios de Trabajo: administrar la configuración del espacio de trabajo
- Gestión de Equipos: administrar miembros del equipo
- Límites de Velocidad: comprender los límites de velocidad de la API