POST /api/v1/templates/{templateId}/test-send
Envoie un seul e-mail — le modèle en l'état — à l'adresse de votre choix, pour qu'un humain puisse vérifier le rendu dans une vraie boîte de réception avant qu'une campagne ne soit construite dessus. C'est le pendant côté API du bouton « Envoyer un test » de l'écran du modèle.
json
{"success": true, "data": {"templateId": "…", "email": "you@example.com", "status": "test_sent"}}Un test consomme un vrai envoi. Il part par le même chemin qu'une campagne — même adresse d'expéditeur que celle qu'utilisera la campagne, même jeu de configuration, même objet et même HTML, sans préfixe
[TEST] — et compte dans le quota d'envoi sur 24 h. Contrairement à POST /api/v1/render, cet endpoint n'est pas gratuit à appeler en boucle.subject et content remplacent ce qui est rendu, jamais qui vous êtes. Ils existent pour que l'éditeur puisse tester le brouillon qu'il affiche, avant l'enregistrement. Le templateId décide toujours de tout ce qui compte : quelle organisation a le droit d'envoyer, quelle liste de suppression est vérifiée, et quelle identité signe le message. Passer du HTML ne transforme pas cet endpoint en envoi libre.
Ce qu'un test écrit : rien. Aucune ligne d'envoi n'est créée, donc aucune statistique ne bouge nulle part. Deux conséquences en découlent, les mêmes que pour un test de campagne :
| Dans un vrai envoi | Dans un test |
|---|---|
| Pixel de suivi des ouvertures | Absent — le pixel est adressé par une ligne d'envoi |
| Liens réécrits pour les clics | Non réécrits — le suivi des clics est adressé par une ligne d'envoi |
| Balises de fusion par destinataire | Données d'exemple de l'aperçu, les mêmes que celles du panneau d'aperçu |
| Lien de désabonnement | Un lien d'aperçu qui ne désabonne personne |
| Condition | Réponse |
|---|---|
| tout est autorisé | 200 — le test a été envoyé |
email absent ou mal formé | 400 — rien n'a été envoyé |
| aucun lien de désabonnement dans le contenu | 400 — même vérification que /render, rien n'est envoyé |
| envoi en masse coupé sur tout AgentsMail | 409 — rien n'a été envoyé |
| organisation non autorisée à envoyer | 409 — rien n'a été envoyé |
| adresse sur la liste de suppression de l'organisation | 409 — rien n'a été envoyé |
| plafond de tests dépassé | 409 — 10 tests par heure et par utilisateur |
| inconnu, ou d'une autre organisation | 404 |
Le plafond de tests est partagé avec les tests de campagne. Dix tests par heure et par utilisateur, campagnes et modèles confondus — l'épuiser sur
/campaigns/{campaignId}/test-send bloque aussi cet endpoint, et inversement. Le plafond est appliqué côté service, si bien que l'écran et l'API puisent dans le même budget : aucun des deux ne permet de contourner l'autre.Autorisation
| Rôle dans l'organisation | Cet endpoint |
|---|---|
OWNER | Autorisé |
ADMIN | Autorisé |
MEMBER | Refusé — 403 |
Corps de la requête
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
email | string | oui | Où part le test |
subject | string | non | Remplace le defaultSubject du modèle pour ce test uniquement |
preheader | string | non | Jusqu'à 200 caractères, le texte d'aperçu à essayer. Un modèle n'en stocke aucun — sans lui, le bloc masqué du HTML reste vide |
content | string | non | Remplace le HTML du modèle pour ce test uniquement |
Exemple
bash
curl -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
"https://www.agentsmail.io/api/v1/templates/$TEMPLATE_ID/test-send" \
-d '{ "email": "you@example.com" }'Réponse
200 OK— l'appel a réussi.401 Unauthorized— clé absente ou invalide, ou son propriétaire a quitté l'organisation.403 Forbidden— le propriétaire de la clé estmemberde l'organisation, pasadmin.404 Not Found— ressource inexistante, ou elle appartient à une autre organisation. L'API ne confirme jamais qu'un identifiant existe à un appelant qui n'y a pas droit.429 Too Many Requests— plus de 120 requêtes en une minute pour cette clé.
Champs de la réponse
| Champ | Type | Description |
|---|---|---|
success | boolean | Indique si l'opération a réussi |
data.status | string | sent, ou la raison pour laquelle il n'est pas parti |
Exemple de réponse
json
{
"success": true,
"data": {
"status": "subscribed"
}
}