Réglages

Tout ce pour quoi une organisation doit être configurée, et l'appel unique qui répond à « puis-je envoyer, et sinon pourquoi ».

Puis-je envoyer ? — l'appel unique

GET /api/v1/me y répond. Plusieurs garde-fous distincts peuvent refuser un envoi, et jusqu'ici ils refusaient sans dire lequel : ce bloc les nomme.
bash
curl -H "x-api-key: $AGENTMAIL_API_KEY" "https://www.agentsmail.io/api/v1/me"
json
{
  "success": true,
  "data": {
    "organization": {"id": "…", "name": "Atelier Nord", "slug": "atelier-nord"},
    "organizationRole": "admin",
    "keyId": "…",
    "sending": {
      "ready": false,
      "blockers": ["domain_not_verified"],
      "setup": {
        "status": "dns_pending",
        "provisioning": "provisioned"
      }
    }
  }
}

Codes de blocage

Ils sont stables et jamais traduits — c'est une interface machine. Construisez votre remédiation sur eux, pas sur un message.
CodeCe que cela signifieComment le lever
sending_disabledL'envoi est coupé sur toute l'applicationRien de possible depuis l'API
organization_not_allowedL'organisation ne figure pas sur la liste des organisations autorisées à envoyerDemandez à l'opérateur de l'autoriser
sending_pausedLe fournisseur d'e-mail a suspendu l'envoi pour cette organisationRien depuis l'API — voir ci-dessous
domain_not_verifiedUn domaine est déclaré mais son DKIM n'est pas SUCCESSPubliez les enregistrements DNS, puis verify
domain_ownership_unprovenLe DKIM est SUCCESS, mais cette organisation n'a pas prouvé qu'elle possède le domainePubliez le TXT _agentmail-challenge, puis verify
sender_not_on_verified_domainUn domaine est vérifié, mais l'adresse d'expéditeur par défaut n'est pas dessus (ni sur l'un de ses sous-domaines)Promouvez ou définissez une adresse sur le domaine vérifié
no_sender_identityLe carnet d'adresses d'expéditeur n'a pas d'adresse par défaut — signalé uniquement en présence d'un vrai blocageAjoutez une adresse (POST /api/v1/settings/identities)
sending_paused n'est pas quelque chose que vous pouvez réessayer. Il apparaît quand le fournisseur d'e-mail suspend l'organisation — pour une question de réputation, en général un taux de rebonds ou de plaintes. Tout envoi à vos contacts est refusé tant qu'il est présent : campagnes, séquences, confirmations d'opt-in. L'envoi de test de campagne reste disponible, pour que vous puissiez toujours vérifier le rendu d'une campagne pendant que vous réglez la suspension — il part sous l'adresse de l'application, pas la vôtre. Le blocage se lève tout seul quand le fournisseur réactive l'envoi, et jamais depuis l'API. Corrigez ce qui l'a provoqué — nettoyez vos listes, arrêtez d'importer des contacts froids — et parlez-en à l'opérateur.
no_sender_identity seul n'est pas un blocage. Sans identité d'expéditeur définie, les e-mails partent quand même sous l'adresse de l'application. Il n'apparaît que lorsque quelque chose d'autre bloque déjà, pour vous dire que le compte est nu.
sender_not_on_verified_domain est un vrai blocage, et c'est à vous de le corriger. Un domaine vérifié ne vous permet d'envoyer que depuis ce domaine : avec codemail.io vérifié, hello@codemail.io et news@news.codemail.io partent, hello@example.org non. Sans cette vérification, le fournisseur accepte le lot puis fait échouer chaque message avec « Email address is not verified » — et rien dans le produit ne vous dirait pourquoi. Il n'apparaît qu'une fois au moins un domaine vérifié : avant cela, définissez librement l'adresse d'expéditeur.

Statut de configuration

sending.setup est le même état que celui que le propriétaire du compte lit à l'écran, sous forme d'un code unique au lieu d'une liste. Il est purement informatif : il n'entre jamais dans blockers et ne change jamais ready. Conditionnez vos envois à ready, et servez-vous de setup.status pour dire où en est le compte en un mot. status est déduit, la première correspondance l'emporte, dans cet ordre :
statusQuandQue faire
suspendedLe fournisseur d'e-mail a suspendu l'envoi pour cette organisationRien depuis l'API — voir l'encadré
sending_disabledL'envoi est coupé sur toute l'applicationAttendre — rien de possible depuis l'API
not_allowedL'organisation ne figure pas sur la liste des organisations autorisées à envoyerDemandez à l'opérateur de l'autoriser
verification_failedL'envoi est bloqué par les domaines, et l'un d'eux a échoué à la vérification DKIMRevérifiez les enregistrements DNS, puis verify
dns_pendingL'envoi est bloqué par les domaines pour toute autre raison, y compris aucun domaine déclaréDéclarez un domaine, publiez le DNS, verify
ownership_pendingLe DKIM a réussi, mais la propriété du domaine n'est pas encore prouvéePubliez le TXT de preuve, puis verify
sender_mismatchUn domaine est vérifié, mais l'adresse d'expéditeur par défaut n'est pas dessusPATCH /api/v1/settings/sending
incompleteRien ne bloque, mais l'isolation d'envoi n'est pas entièrement en placeRien — l'opérateur relance l'opération
activeRien ne bloque, et l'isolation est en placeEnvoyez
provisioning est l'état brut de l'isolation — none, provisioned ou incomplete. none n'est pas une anomalie : cela signifie simplement que rien n'a encore été tenté, et cela n'empêche pas un envoi.
Une organisation qui n'est pas autorisée à envoyer ne lit jamais active. C'est tout l'intérêt de l'ordre : un feu vert pour un envoi que le service refuserait est pire que pas de feu du tout. Un domaine vérifié ne rend pas un compte autorisé, et setup.status le dit.
Deux domaines, l'un vérifié et l'autre en échec ? blockers est vide, ready vaut true, et setup.status vaut active — le compte envoie sans problème. verification_failed n'apparaît que lorsque l'échec bloque réellement.

Tout lire d'un coup

GET /api/v1/settings renvoie l'état complet en un seul appel.
json
{
  "success": true,
  "data": {
    "sending": {
      "senderEmail": "bonjour@atelier-nord.fr",
      "senderName": "Atelier Nord",
      "postalAddress": "12 rue des Lilas\n59000 Lille",
      "effectiveSender": "Atelier Nord <bonjour@atelier-nord.fr>"
    },
    "optin": {
      "required": true,
      "subject": "Confirme ton inscription",
      "content": "<div>…</div>",
      "customized": false
    },
    "readiness": {
      "ready": true,
      "blockers": [],
      "setup": {"status": "active", "provisioning": "provisioned"}
    }
  }
}
readiness est ici exactement le même objet que celui renvoyé par GET /api/v1/me sous sending, setup compris — une question, une réponse, deux endroits où la lire. effectiveSender est ce qui partira réellement, repli compris — c'est ce que vous voulez vérifier, pas la colonne.

Identité d'expéditeur

Une organisation tient un carnet d'adresses d'expéditeur : une adresse par domaine vérifié, et exactement l'une d'elles marquée par défaut. L'adresse par défaut signe tout ce qui ne nomme pas sa propre adresse : les séquences, les confirmations d'inscription, et toute campagne qui a omis sendingIdentityId. Une campagne peut nommer l'une des autres adresses — voir POST /api/v1/campaigns — et c'est alors cette adresse qui la signe, quelle que soit l'adresse par défaut par la suite.
senderEmail et senderName dans GET /api/v1/settings décrivent l'adresse par défaut. Le contrat n'a pas changé : lisez-les exactement comme avant. Le carnet complet se trouve à GET /api/v1/settings/identities.

Lire et écrire l'adresse par défaut — inchangé

PATCH /api/v1/settings/sending — rôle admin requis.
bash
curl -X PATCH -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"senderName":"Atelier Nord"}' \
  "https://www.agentsmail.io/api/v1/settings/sending"
Un champ omis reste tel quel. Un champ à null est effacé et revient à l'adresse de l'application. Sans cette distinction, définir seulement le nom affiché effacerait l'adresse d'expéditeur. Cet endpoint agit sur l'adresse par défaut, et sur elle seule :
CorpsEffet
senderEmail (non nul)Définit l'adresse par défaut — l'identité est créée si le carnet est vide
senderEmail: nullRetire l'adresse par défaut du carnet ; l'envoi revient à l'adresse de l'application
senderName seulRenomme l'adresse par défaut. Refusé avec 400 quand il n'y a pas d'adresse par défaut — un nom affiché n'a nulle part où vivre sans adresse
postalAddressReste sur l'organisation : une mention légale, pas un attribut de l'expéditeur
senderEmail: null est refusé quand le carnet contient plus d'une adresse. Retirer l'adresse par défaut alors que d'autres restent laisserait le compte avec un carnet plein et rien pour signer. Promouvez d'abord une autre adresse, avec PATCH /api/v1/settings/identities/{identityId}.

Le carnet d'adresses

EndpointRôleCe qu'il fait
GET /api/v1/settings/identitiesmemberLe carnet complet, l'adresse par défaut en premier
POST /api/v1/settings/identitiesadminAjoute une adresse — {senderEmail, senderName?, isDefault?}
PATCH /api/v1/settings/identities/{identityId}adminChange l'adresse ou le nom affiché, ou la promeut avec {"isDefault": true}
DELETE /api/v1/settings/identities/{identityId}adminRetire une adresse du carnet
bash
curl -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"senderEmail":"news@atelier-nord.fr","senderName":"Atelier Nord"}' \
  "https://www.agentsmail.io/api/v1/settings/identities"
json
{
  "success": true,
  "data": {
    "id": "…",
    "senderEmail": "news@atelier-nord.fr",
    "senderName": "Atelier Nord",
    "isDefault": false,
    "createdAt": "2026-08-17T09:00:00.000Z"
  }
}
La première adresse que vous ajoutez devient d'elle-même l'adresse par défaut. Un compte ne détient jamais plusieurs adresses sans rien pour signer — cela ne lèverait aucun blocage et ne changerait aucun envoi.
L'adresse par défaut ne peut pas être supprimée tant que d'autres adresses restent, et {"isDefault": false} est refusé. Les deux répondent 400 en nommant l'adresse. Promouvoir en silence une adresse restante changerait l'expéditeur de chaque campagne programmée, de chaque séquence en cours et de chaque confirmation d'opt-in — sans que personne ne l'ait demandé. Promouvez d'abord une autre adresse, puis supprimez.Supprimer la dernière adresse est autorisé : l'envoi revient alors à l'adresse de l'application, et no_sender_identity le signale.
Une adresse nommée par une campagne ne peut pas non plus être supprimée — quel que soit le statut de cette campagne, brouillon et déjà envoyée comprises. Le refus est un 400 qui nomme les campagnes. L'alternative serait un envoi de masse programmé qui change d'expéditeur en silence, ce que ce produit refuse précisément de faire. Pointez ces campagnes vers une autre adresse, ou de nouveau vers l'adresse par défaut avec {"sendingIdentityId": null}, puis supprimez.
Les séquences et les confirmations d'opt-in prennent toujours l'adresse par défaut. Il n'y a pas d'expéditeur par séquence : le choix n'existe que sur les campagnes, via sendingIdentityId.

L'adresse d'expéditeur doit être sur un domaine vérifié

Chaque adresse du carnet — pas seulement celle par défaut — doit vivre sur l'un de vos domaines vérifié et prouvé. Dès que l'organisation a au moins un domaine vérifié, senderEmail doit être sur ce domaine, ou sur l'un de ses sous-domaines. Tout le reste est refusé avec 400, en nommant les deux faits :
bash
curl -X PATCH -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"senderEmail":"hello@example.org"}' \
  "https://www.agentsmail.io/api/v1/settings/sending"
json
{
  "error": "Erreur de validation : Votre domaine codemail.io est vérifié — mais hello@example.org n’est pas dessus. Utilisez une adresse sur ce domaine ou sur l’un de ses sous-domaines."
}
Sans domaine vérifié pour l'instant, n'importe quelle adresse est acceptée : l'expéditeur est souvent défini avant la publication du DNS. domain_not_verified bloque tout de même les envois jusqu'à ce qu'un domaine soit vérifié, et sender_not_on_verified_domain prend le relais ensuite.

Réglages d'inscription

PATCH /api/v1/settings/optin — rôle admin requis.
bash
curl -X PATCH -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"required":true,"subject":"Confirm your sign-up","content":"<p><a href=\"{{confirmationUrl}}\">Confirm</a></p>"}' \
  "https://www.agentsmail.io/api/v1/settings/optin"
ChampEffet
requiredDécide des nouvelles inscriptions : true signifie pending avec confirmation ; false signifie subscribed sans confirmation. L'ancien champ doubleOptIn de l'API des contacts est ignoré
subjectObjet de l'e-mail de confirmation
contentSon HTML
Le contenu doit contenir {{confirmationUrl}}. Sans elle, le destinataire n'a aucun moyen de confirmer, et le double opt-in casse en silence. Un contenu qui ne la contient pas est refusé avec 400, en nommant la variable manquante.
Variables disponibles : {{confirmationUrl}} (obligatoire), {{firstName}}, {{lastName}}, {{email}}, {{postalAddress}}, {{currentYear}}. Il n'y a pas de variable de désabonnement — le destinataire n'est pas encore abonné. Renvoyer le contenu par défaut n'est pas une personnalisation. Un contenu identique à celui par défaut est stocké vide, pour que l'organisation continue d'hériter de ses améliorations futures. customized vous dit dans quel cas vous êtes.

Tester l'e-mail de confirmation

POST /api/v1/settings/optin/test-send — rôle admin requis.
bash
curl -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"email":"you@example.com","content":"<p><a href=\"{{confirmationUrl}}\">Confirm</a></p>"}' \
  "https://www.agentsmail.io/api/v1/settings/optin/test-send"
Le content et le subject du corps l'emportent sur ce qui est stocké : essayez avant de publier. Le lien de confirmation d'un test est factice — tester trois fois ne doit pas mettre en circulation trois jetons réels et valides. Un test est un envoi réel : il passe les mêmes garde-fous que n'importe quel autre. Il répond {"status":"blocked"} (envoi coupé sur toute l'application), {"status":"not_allowed"} (organisation non autorisée, ou domaine non vérifié) ou {"status":"send_refused"} (le fournisseur a refusé l'envoi) plutôt que d'échouer, pour que vous puissiez distinguer un refus d'une erreur — et distinguer les refus entre eux.