MailLandDocs
Envoi d'emails

Templates

Créez et gérez des templates d'e-mails réutilisables avec substitution dynamique de variables

Créez des templates d'e-mails réutilisables avec des variables dynamiques. Les templates stockent le sujet, le contenu HTML et le contenu texte de vos e-mails, afin que vous puissiez envoyer des e-mails personnalisés sans reconstruire le contenu à chaque requête.

Créer un template

POST https://api.mail.land/v1/templates
Create a template
curl -X POST https://api.mail.land/v1/templates \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Order Confirmation",
    "subject": "Your order #{{orderNumber}} is confirmed",
    "htmlContent": "<h1>Thanks, {{firstName}}!</h1><p>Order #{{orderNumber}} has been confirmed. Total: {{total}}</p>",
    "textContent": "Thanks, {{firstName}}! Order #{{orderNumber}} has been confirmed. Total: {{total}}",
    "categoryId": "k3v9q2m7xw4tpa"
  }'
Response : 201 Created
{
  "id": "t8x2m4q9zk7wpr",
  "name": "Order Confirmation",
  "subject": "Your order #{{orderNumber}} is confirmed",
  "htmlContent": "<h1>Thanks, {{firstName}}!</h1>...",
  "textContent": "Thanks, {{firstName}}!...",
  "categoryId": "k3v9q2m7xw4tpa",
  "categoryName": "Transactional",
  "categoryColor": "#3B82F6",
  "createdAt": "2026-02-17T10:00:00Z",
  "updatedAt": null
}

Règles de validation

ChampContrainte
nameObligatoire, 200 caractères maximum
subjectObligatoire, 500 caractères maximum
htmlContentObligatoire, 1 Mo maximum
textContentOptionnel, 1 Mo maximum
categoryIdOptionnel, doit référencer une catégorie existante

Syntaxe des variables

Utilisez des doubles accolades pour la substitution de variables :

Template with variables
<h1>Hello {{firstName}},</h1>
<p>Your order #{{orderNumber}} shipped on {{shipDate}}.</p>
<p>Track your package: <a href="{{trackingUrl}}">{{trackingNumber}}</a></p>

Les variables sont remplacées au moment de l'envoi. Transmettez les valeurs via le champ variables dans votre requête d'envoi :

Send with template variables
{
  "from": { "email": "[email protected]" },
  "to": [
    {
      "email": "[email protected]",
      "variables": {
        "firstName": "Jane",
        "orderNumber": "ORD-12345",
        "shipDate": "Feb 17, 2026",
        "trackingUrl": "https://track.example.com/ABC123",
        "trackingNumber": "ABC123"
      }
    }
  ],
  "templateId": "t8x2m4q9zk7wpr"
}

Les variables fonctionnent à la fois dans subject et dans htmlContent/textContent. Chaque {{variable}} qu'un modèle utilise doit avoir une valeur, dans les variables de la requête ou dans les variables propres au destinataire. Si l'une n'a pas de valeur, MailLand n'envoie pas le message avec l'espace réservé : POST /v1/transactional/send répond 422 TEMPLATE_VARIABLE_MISSING en nommant les variables manquantes, et POST /v1/transactional/send-batch ignore ce destinataire et le liste dans rejectedRecipients. Les campagnes et les automatisations ignorent aussi ce destinataire. Un htmlContent en ligne envoyé sans aucune variables part tel qu'il est écrit. Les espaces réservés sont exactement {{name}}, sans filtres, conditions ni boucles. Un modèle indique grammarVersion: "legacy-v1", la seule grammaire aujourd'hui ; vous pouvez omettre ce champ à la création ou à la modification d'un modèle.

Valeurs par défaut

Un modèle peut porter une valeur par défaut pour chaque champ de contact qu'il utilise, afin qu'un abonné sans valeur pour ce champ reçoive quand même l'e-mail. Définissez-les avec variableDefaults, un objet associant nom d'espace réservé et valeur, à la création et à la mise à jour. Elles sont aussi renvoyées quand vous récupérez, listez ou dupliquez un modèle.

Modèle avec valeur par défaut
{
  "name": "Welcome",
  "subject": "Hello {{firstName}}",
  "htmlContent": "<p>Hi {{firstName}}</p>",
  "variableDefaults": { "firstName": "cher client" }
}

Règles :

  • Les valeurs par défaut s'appliquent uniquement aux envois de campagnes et d'automatisations. La valeur non vide propre au destinataire l'emporte toujours sur la valeur par défaut.
  • Un champ sans valeur ni valeur par défaut est toujours refusé : MailLand n'envoie jamais un {{firstName}} littéral.
  • Les envois transactionnels par API et SMTP ne sont pas concernés. Les valeurs y viennent de votre requête, et une valeur manquante est refusée comme décrit plus haut.
  • À la mise à jour, omettre variableDefaults conserve les valeurs enregistrées. Envoyez {} pour les effacer.
  • Les noms suivent la syntaxe des espaces réservés. email et subscriberId sont toujours fournis et n'ont pas de valeur par défaut. Une valeur tient sur une ligne, 200 caractères au plus, et un modèle contient au plus 50 valeurs par défaut.

Dans l'éditeur du tableau de bord, chaque espace réservé a un champ de valeur par défaut qui indique combien d'abonnés n'ont pas ce champ, et l'enregistrement vous avertit si un champ manquant chez des abonnés n'a pas de valeur par défaut.

Prévisualiser un template

Prévisualisez un template avec des valeurs d'exemple automatiquement remplies pour les variables détectées :

GET https://api.mail.land/v1/templates/{id}/preview
Preview a template
curl https://api.mail.land/v1/templates/t8x2m4q9zk7wpr/preview \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Preview response
{
  "id": "t8x2m4q9zk7wpr",
  "name": "Order Confirmation",
  "subject": "Your order #12345 is confirmed",
  "renderedHtml": "<h1>Thanks, John!</h1><p>Order #12345 has been confirmed.</p>",
  "renderedText": "Thanks, John! Order #12345 has been confirmed."
}

Dupliquer un template

Clonez un template existant :

POST https://api.mail.land/v1/templates/{id}/duplicate
Duplicate a template
curl -X POST https://api.mail.land/v1/templates/t8x2m4q9zk7wpr/duplicate \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Le duplicata reçoit un nom généré automatiquement : "Order Confirmation (Copy)". Si une copie existe déjà, le nom est incrémenté : "Order Confirmation (Copy 2)", etc.

Catégories de templates

Organisez les templates en catégories avec des couleurs optionnelles.

Créer une catégorie

POST https://api.mail.land/v1/templates/categories
Create a category
curl -X POST https://api.mail.land/v1/templates/categories \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Transactional",
    "description": "Order confirmations, receipts, and shipping notifications",
    "color": "#3B82F6"
  }'
ChampContrainte
nameObligatoire, 1 à 100 caractères
descriptionOptionnel, 500 caractères maximum
colorOptionnel, format hexadécimal (#3B82F6 ou #38F)

Lister les catégories

GET https://api.mail.land/v1/templates/categories
List template categories
curl https://api.mail.land/v1/templates/categories \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Categories response
{
  "categories": [
    {
      "id": "k3v9q2m7xw4tpa",
      "name": "Transactional",
      "description": "Order confirmations, receipts",
      "color": "#3B82F6",
      "templateCount": 12,
      "createdAt": "2026-01-15T10:00:00Z"
    }
  ],
  "totalCount": 3
}

Lister les templates

GET https://api.mail.land/v1/templates?limit=50
List templates
curl "https://api.mail.land/v1/templates?limit=50" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Filtrer par catégorie :

GET https://api.mail.land/v1/templates?categoryId=k3v9q2m7xw4tpa
List templates by category
curl "https://api.mail.land/v1/templates?categoryId=k3v9q2m7xw4tpa" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Template list response
{
  "items": [
    {
      "id": "t8x2m4q9zk7wpr",
      "name": "Order Confirmation",
      "subject": "Your order #{{orderNumber}} is confirmed",
      "htmlContent": "...",
      "categoryName": "Transactional",
      "categoryColor": "#3B82F6",
      "createdAt": "2026-02-17T10:00:00Z"
    }
  ],
  "nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
  "hasMore": true
}

Mettre à jour un template

PUT https://api.mail.land/v1/templates/{id}

Tous les champs sont obligatoires dans la requête de mise à jour (il s'agit d'un remplacement complet, pas d'une mise à jour partielle) :

Update a template
curl -X PUT https://api.mail.land/v1/templates/t8x2m4q9zk7wpr \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Order Confirmation v2",
    "subject": "Order #{{orderNumber}} confirmed - {{companyName}}",
    "htmlContent": "<h1>Thanks, {{firstName}}!</h1><p>Updated template content.</p>",
    "textContent": "Thanks, {{firstName}}! Updated template content.",
    "categoryId": "k3v9q2m7xw4tpa"
  }'

Supprimer un template

DELETE https://api.mail.land/v1/templates/{id}
Delete a template
curl -X DELETE https://api.mail.land/v1/templates/t8x2m4q9zk7wpr \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Renvoie 204 No Content en cas de succès. Un modèle supprimé ne peut plus être récupéré, listé ni utilisé pour l'envoi : une demande d'envoi qui le référence, immédiate ou planifiée, est rejetée avec 400 TEMPLATE_NOT_FOUND, et une planification dont le modèle est supprimé avant son échéance est rejetée de la même façon au moment de l'envoi.

Utiliser les templates lors de l'envoi

Référencez un template par son identifiant dans votre requête d'envoi. Le sujet et le contenu du template sont utilisés, avec les variables substituées :

Send with template
{
  "from": { "email": "[email protected]" },
  "to": [
    {
      "email": "[email protected]",
      "variables": {
        "firstName": "Jane",
        "orderNumber": "ORD-12345"
      }
    }
  ],
  "templateId": "t8x2m4q9zk7wpr",
  "variables": {
    "companyName": "Acme Inc"
  }
}

Lorsque templateId est defini, le sujet rendu du template est toujours utilise ; un subject dans la requete d'envoi est ignore.

Limites du forfait

Le nombre de templates que vous pouvez créer dépend de votre forfait. Si vous atteignez la limite, la création d'un nouveau template renvoie 403 PLAN_LIMIT_REACHED.

Étapes suivantes

  • REST API : envoyer des e-mails avec des templates
  • Envoi par lots : utiliser des templates avec les envois par lots
  • E-mails programmés : utiliser des templates via /v1/transactional/send avec scheduledAt (le point de terminaison de planification n'a pas de champ templateId)

Sur cette page