E-mails transactionnels
POST /smtp/email envoie un e-mail par l'infrastructure du site : relais d'envoi (SMTP ou SES)
configuré dans la console, journal des envois, suivi des ouvertures et des clics.
{
"sender": { "name": "Ma Boutique", "email": "contact@ma-boutique.fr" },
"to": [{ "email": "client@example.com", "name": "Camille" }],
"subject": "Votre commande {{ params.order.id }}",
"htmlContent": "<p>Merci {{ contact.FIRSTNAME | default: \"\" }} !</p>",
"params": { "order": { "id": "1042" } },
"tags": ["commande"]
}
Réponse 201 : { "messageId": "<…@smtp-relay.mailin.fr>" }.
Contenu
Fournissez au choix :
htmlContentet/outextContent, avecsubject;- ou
templateId, l'identifiant d'un modèle (voir « Modèles » plus bas). Le modèle doit être actif ; son expéditeur, son objet, son adresse de réponse, son étiquette (tag) et sa pièce jointe servent de valeurs par défaut.
Si textContent est absent, une version texte est déduite du HTML. Avec textContent seul, la
partie HTML reprend le texte dans un bloc préformaté.
Expéditeur
sender accepte { "email", "name" } ou { "id" } (un expéditeur créé avec /senders). Sans
sender, l'expéditeur du modèle est utilisé, sinon l'expéditeur par défaut du site.
Paramètres et langage de modèle
params alimente les variables du contenu et de l'objet. Les attributs du contact (le premier
destinataire to, s'il existe dans vos contacts) sont disponibles sous contact.* ;
contact.EMAIL est toujours renseigné.
Bonjour {{ contact.FIRSTNAME | default: "client" }},
Commande n°{{ params.order.id }} : total {{ params.order.total | floatformat: 2 }} €
{% if params.vip %}Livraison offerte !{% elif params.pays == "BE" %}Livraison : 6,90 €{% else %}Livraison : 4,90 €{% endif %}
{% for item in params.items %}{{ forloop.counter }}. {{ item.name }}
{% empty %}Aucun article.{% endfor %}
Filtres : default, upper, lower, capfirst, title, truncatechars, length,
floatformat, join, escape, safe. Conditions : == != > < >= <= in and or not.
Dans une boucle : forloop.counter, forloop.counter0, forloop.first, forloop.last.
Dans htmlContent, les valeurs sont échappées en HTML, sauf avec | safe ; l'objet et
textContent ne sont pas échappés.
Destinataires, versions, pièces jointes
to(obligatoire, 99 destinataires max.),cc,bcc: tableaux de{ "email", "name" };replyTo: un objet{ "email", "name" };tags: tableau de chaînes, utilisé pour filtrer les statistiques ;messageVersions: jusqu'à 1 000 variantes dans une seule requête. Chaque version peut redéfinirto,cc,bcc,replyTo,params(fusionnés avec ceux de la requête),subject,htmlContentettextContent. La réponse contient alorsmessageIds;attachment:[{ "name": "facture.pdf", "content": "<base64>" }]ou[{ "url": "https://…/facture.pdf" }]. L'URL doit être publique (http ou https) ; sansname, le nom est tiré de l'URL ;headers: en-têtes personnalisés transmis tels quels.
Idempotence
Ajoutez "headers": { "idempotencyKey": "commande-1042" } : pendant 24 h, une requête
répétée avec la même clé renvoie le même messageId (ou les mêmes messageIds) sans
renvoyer l'e-mail.
Planification
scheduledAt (ISO 8601, 72 h max.) met l'envoi en file : réponse 202 avec messageId
(messageIds avec des versions, plus un batchId quand il y en a plusieurs). Une date passée
ou à moins de 30 secondes envoie tout de suite (201).
| Action | Requête |
|---|---|
| État | GET /smtp/emailStatus/{messageId ou batchId} : queued, inProgress, processed ou error |
| Annulation | DELETE /smtp/email/{messageId ou batchId} : 204, ou 404 si l'envoi n'est plus planifié |
Le messageId contient <, > et @ : encodez-le dans l'URL.
Liste de blocage
Avant l'envoi, chaque destinataire to est comparé à la liste de blocage transactionnelle du
site, aux domaines bloqués et aux suppressions de la plateforme. Un destinataire bloqué ne
reçoit rien et produit un événement blocked ; la requête reste en 201. Un rejet
définitif (hard bounce) ou une plainte pour spam ajoute automatiquement l'adresse à la liste
de blocage.
| Action | Requête |
|---|---|
| Contacts bloqués | GET /smtp/blockedContacts (startDate, endDate, senders, limit ≤ 100) |
| Débloquer un contact | DELETE /smtp/blockedContacts/{email} |
| Domaines bloqués | GET /smtp/blockedDomains, POST /smtp/blockedDomains avec { "domain": "example.com" } |
| Débloquer un domaine | DELETE /smtp/blockedDomains/{domain} |
| Effacer les rejets définitifs | POST /smtp/deleteHardbounces (contactEmail, startDate, endDate, tous facultatifs) |
Erreurs d'envoi
| Statut | code |
Cas |
|---|---|---|
| 400 | missing_parameter |
ni htmlContent, ni textContent, ni templateId ; to ou subject absent ; aucun expéditeur |
| 400 | invalid_parameter |
adresse invalide, modèle inactif, sender.id inconnu, URL de pièce jointe inaccessible ou non publique |
| 400 | out_of_range |
plus de 99 to, plus de 1 000 versions, scheduledAt au-delà de 72 h |
| 404 | document_not_found |
templateId inconnu |
Journaux et statistiques
| Besoin | Endpoint |
|---|---|
| Liste des envois | GET /smtp/emails (email, messageId, templateId, startDate, endDate, limit ≤ 1000, offset, sort) |
| Détail d'un envoi (corps, événements) | GET /smtp/emails/{uuid} |
| Événements | GET /smtp/statistics/events (event, email, messageId, templateId, tags, dates, limit ≤ 5000) |
| Totaux | GET /smtp/statistics/aggregatedReport (tag, dates) |
| Par jour | GET /smtp/statistics/reports (tag, dates, limit ≤ 30) |
| Effacer un journal | DELETE /smtp/log/{email ou messageId} |
Pour les événements et les rapports, les dates se passent avec startDate et endDate
ensemble, ou avec days ; par défaut, ils portent sur les 30 derniers jours. Valeurs de event : requests, delivered,
opened, clicks, bounces, hardBounces, softBounces, deferred, spam, blocked,
invalid, unsubscribed, error. Les envois planifiés ou annulés n'apparaissent pas dans
/smtp/emails.
Modèles
| Action | Requête |
|---|---|
| Lister | GET /smtp/templates (templateStatus=true ou false, limit, offset, sort) |
| Créer | POST /smtp/templates : templateName, subject, sender et htmlContent (ou htmlUrl) obligatoires ; replyTo, tag, toField, attachmentUrl, isActive facultatifs. Réponse 201 { "id" } |
| Lire, modifier, supprimer | GET, PUT, DELETE /smtp/templates/{templateId} |
| Envoi de test | POST /smtp/templates/{templateId}/sendTest avec { "emailTo": ["…"] } (objet préfixé par [Test]) |
| Aperçu rendu | POST /smtp/template/preview avec templateId, params et email (contact dont les attributs alimentent contact.*) |
Un modèle créé est actif par défaut ; passez "isActive": false pour le créer inactif (il ne peut
alors pas servir à POST /smtp/email).