Envoi par lot
Envoyez des e-mails a plusieurs destinataires en un seul appel API
L'envoi par lot est uniquement disponible avec les identifiants de flux Marketing. Les identifiants transactionnels retournent 400 BATCH_NOT_ALLOWED_FOR_TRANSACTIONAL. Cela empeche l'utilisation abusive des flux transactionnels pour l'envoi d'e-mails en masse.
Envoyer un lot
POST https://api.mail.land/v1/transactional/send-batchcurl -X POST https://api.mail.land/v1/transactional/send-batch \
-H "X-API-Key: ml_pem_Ab3Kx9mN2pQ7rT4wL8yD..." \
-H "Content-Type: application/json" \
-d '{
"from": {
"email": "[email protected]",
"name": "Your Company"
},
"recipients": [
{
"email": "[email protected]",
"name": "Alice",
"variables": { "firstName": "Alice", "plan": "Pro" }
},
{
"email": "[email protected]",
"name": "Bob",
"variables": { "firstName": "Bob", "plan": "Starter" }
}
],
"subject": "Hi {{firstName}}, check out what'\''s new",
"htmlContent": "<h1>Hey {{firstName}}!</h1><p>Your {{plan}} plan just got an upgrade.</p>",
"variables": {
"companyName": "Acme Inc",
"year": "2026"
},
"tags": ["product-update", "february-2026"],
"batchName": "February Product Update"
}'Champs de la requete
| Champ | Type | Requis | Description |
|---|---|---|---|
from | object | Oui | Adresse de l'expediteur (email et name optionnel) |
recipients | array | Oui | Liste des destinataires (note : recipients, pas to) |
recipients[].email | string | Oui | E-mail du destinataire |
recipients[].name | string | Non | Nom d'affichage du destinataire |
recipients[].variables | object | Non | Variables de template par destinataire |
subject | string | Conditionnel | Requis sauf si vous utilisez templateId |
templateId | string | Non | Utiliser un template enregistre |
htmlContent | string | Conditionnel | Corps HTML (requis si pas de templateId) |
textContent | string | Non | Texte brut de remplacement |
variables | object | Non | Variables globales. Appliquées que templateId soit défini ou non ; en cas de clé identique, la valeur propre du destinataire dans recipients[].variables l'emporte |
replyTo | string | Non | Adresse de reponse |
batchName | string | Non | Nom lisible pour ce lot |
tags | array | Non | Tags pour les statistiques et le filtrage des webhooks |
customHeaders | object | Non | En-tetes d'e-mail personnalises |
tracking | object | Non | Remplacement du suivi des ouvertures/clics |
ipPoolId | string | Non | Réservé aux pools d'IP dédiées. Pas encore disponible : l'envoyer renvoie 400 IP_POOL_NOT_FOUND. À omettre. |
scheduledAt | datetime | Non | Planifier pour un envoi futur, jusqu'à 7 jours à l'avance |
externalBatchId | string | Non | Identifiant de lot de votre système : s'il est fourni, il est renvoyé tel quel comme batchId dans la réponse |
priority | enum | Non | Low, Normal (par defaut), High, Critical |
idempotencyKey | string | Non | Empeche les envois en double pour la meme cle. L'en-tete X-Idempotency-Key est prefere |
Notez la difference de nom de champ : l'envoi par lot utilise recipients tandis que l'envoi unique utilise to.
Reponse
Statut : 202 Accepted
{
"success": true,
"batchId": "batch_f47ac10b58cc43729876fedcba098765",
"messageIds": ["m_a1b2c3...", "m_d4e5f6..."],
"totalRecipients": 2,
"acceptedCount": 2,
"rejectedCount": 0,
"rejectedRecipients": [],
"queuedAt": "2026-02-17T10:30:00Z",
"estimatedCompletion": "2026-02-17T10:35:00Z",
"isSandboxed": false
}| Champ | Type | Description |
|---|---|---|
batchId | string | Identifiant unique du lot |
messageIds | array | Identifiants de message par destinataire (prefixe m_ pour marketing) |
totalRecipients | int | Nombre total de destinataires dans la requete |
acceptedCount | int | Destinataires acceptes pour la livraison |
rejectedCount | int | Destinataires rejetes |
rejectedRecipients | array | Details des destinataires rejetes avec les raisons |
estimatedCompletion | datetime | Temps estime pour la fin du traitement du lot |
Fusion des variables
Les variables par destinataire remplacent les variables globales lorsque les cles se chevauchent :
{
"variables": {
"companyName": "Acme Inc",
"greeting": "Hello"
},
"recipients": [
{
"email": "[email protected]",
"variables": { "greeting": "Dear valued customer" }
},
{
"email": "[email protected]"
}
]
}[email protected]recoit :greeting = "Dear valued customer",companyName = "Acme Inc"[email protected]recoit :greeting = "Hello",companyName = "Acme Inc"
Gestion des erreurs
Erreurs specifiques a l'envoi par lot :
| Statut | Code | Description |
|---|---|---|
400 | BATCH_NOT_ALLOWED_FOR_TRANSACTIONAL | L'identifiant transactionnel ne peut pas envoyer de lots |
400 | VALIDATION_FAILED | Nombre maximum de destinataires par lot depasse (10 000) |
400 | INVALID_REQUEST | scheduledAt de plus de 7 jours à l'avance ("Cannot schedule email more than 7 days in advance") |
400 | TEMPLATE_NOT_FOUND | templateId ne désigne aucun modèle actif de ce compte (également renvoyé pour un modèle supprimé) |
400 | IP_POOL_NOT_FOUND | ipPoolId ne désigne aucun pool assigné à ce compte |
422 | TEMPLATE_VARIABLE_MISSING | Chaque destinataire n'a pas de valeur pour un {{placeholder}} (si ce n'est le cas que pour certains, ils sont ignorés et listés dans rejectedRecipients avec la raison template_variable_missing: name). Rien n'est mis en file |
400 | BATCH_SEND_FAILED | Tous les destinataires sont supprimés |
429 | RATE_LIMIT_EXCEEDED | Limite de débit dépassée (au niveau workspace/plan, pas par identifiant) |
429 | QUOTA_EXCEEDED | Quota mensuel epuise |
Les codes de vérification de compte et de politique documentés pour POST /v1/transactional/send (SENDING_BLOCKED, ACTION_REQUIRED, DAILY_LIMIT_EXCEEDED, MARKETING_PAUSED et les autres) s'appliquent également ici.
Un succes partiel est possible -- certains destinataires peuvent etre acceptes tandis que d'autres sont rejetes (ex. : adresses supprimees). Verifiez rejectedRecipients dans la reponse.
Etapes suivantes
- API REST -- reference d'envoi d'e-mail unique
- Templates -- creer des templates pour les e-mails par lot
- E-mails planifies -- planifier des lots pour plus tard