Référence de l'API

Une API JSON sur HTTPS. 32 points de terminaison, tous versionnés sous /v1. Dernière mise à jour 1 novembre 2026.

Authentification

Chaque requête porte une clé d'API comme jeton bearer. Les clés sont créées sous Clés d'API et affichées une seule fois.

Authorization: Bearer zm_live_...

Une clé porte un ensemble de portées; une requête hors de celles-ci est refusée par un 403 insufficient_scope qui nomme la portée attendue.

PortéePermet
email:messages.sendEnvoyer du courrier.
email:messages.readLire un message ou un destinataire.
email:domains.readLister et inspecter les domaines d'envoi.
email:domains.writeAjouter, vérifier et retirer des domaines.
email:suppressions.readLister les suppressions.
email:suppressions.writeAjouter, retirer et importer des suppressions.
email:stats.readStatistiques, quota et état d'envoi.
email:webhooks.readLister les points de terminaison de webhooks.
email:webhooks.writeCréer, modifier, supprimer et tester des points de terminaison.
email:sandbox.writeAjouter un destinataire de test vérifié en mode bac à sable.
iam:users.readLister les membres de l'équipe et les invitations.
iam:users.writeInviter, changer un rôle, retirer un membre.
Les clés créées avant l'existence des portées ont un accès complet. Elles ont été maintenues plutôt que cassées : si vous détenez une clé ancienne, vous ne verrez jamais de 403 et ne devez pas en conclure que les portées ne sont pas appliquées. Créez une nouvelle clé pour en obtenir une avec portées.

Erreurs

Une erreur est du JSON avec un code machine stable et une phrase pour un humain. Faites correspondre sur error; message peut être reformulé ou traduit.

{
  "error": "insufficient_scope",
  "message": "This API key lacks the email:messages.send scope."
}
StatutSignifie
200Succès.
201Créé — domaine, suppression, point de terminaison ou invitation.
401En-tête Authorization absent, mal formé ou inconnu.
403insufficient_scope — la clé est valide mais n'a pas la portée requise.
404not_found — aucun message, domaine, point de terminaison ou utilisateur sur ce compte.
422La requête a été comprise et refusée. Voir le code d'erreur.
429Débit limité, ou la limite d'envoi quotidienne du compte est atteinte.
500Notre faute. Vous pouvez réessayer.

Les codes possibles sur un 422 comprennent invalid_from, invalid_email, invalid_domain, invalid_url, subject_too_long, body_too_large, file_too_large, reserved_header, too_many_headers et duplicate_header. Quelques validations plus anciennes retournent error sous forme de phrase sans code; traitez une valeur error non reconnue comme un refus à ne pas réessayer tel quel.

Un en-tête que nous posons nous-mêmes ne peut être remplacé, et toute tentative est refusée plutôt qu'ignorée en silence — y compris List-Unsubscribe, Content-Type, From et tout ce qui commence par X-Zedmail-. Un retour chariot ou un saut de ligne dans une valeur d'en-tête est également refusé; nous ne nettoyons jamais pour envoyer quand même.

Idempotence

Envoyez un en-tête Idempotency-Key et une nouvelle tentative de la même requête n'enverra pas un second message. Les clés sont mémorisées pendant 24 heures.

Idempotency-Key: order-18472-receipt

C'est une protection contre le double envoi, non un cache de réponses : une requête qui arrive pendant que la première est encore en vol est refusée plutôt que servie depuis un envoi inachevé.

Limites

LimiteValeur
Objet998 bytes
Corps HTML1 MB
Corps texte1 MB
Messages par lot50
En-têtes personnalisés par message10
Nom d'en-tête personnalisé64 bytes
Valeur d'en-tête personnalisé200 bytes
Tous les en-têtes personnalisés2048 bytes

Envoi

Une adresse par requête. Un 2xx signifie que nous avons accepté le message et en avons pris la responsabilité, non qu'il est arrivé — interrogez le message ou prenez un webhook pour cela.

Méthode Chemin Portée Fait
POST /v1/email/send email:messages.send Envoyer un message.
POST /v1/email/batch email:messages.send Jusqu'à 50 messages en une requête. Retourne un tableau results dans l'ordre d'envoi; un message invalide n'invalide pas les autres.

Champs de la requête

Champ Type Requis Notes
to string oui Adresse du destinataire. Une par requête; utilisez /v1/email/batch pour plusieurs.
subject string — Jusqu'à 998 octets.
html string — Corps HTML. Au moins un de html ou text est requis.
text string — Corps en texte brut. Généré depuis html s'il est omis.
reply_to string — Adresse de réponse.
tags array — Vos propres étiquettes, retournées dans les webhooks et les statistiques. Privées — jamais mises sur le réseau.
headers object — En-têtes personnalisés, nom/valeur. Les noms réservés sont refusés par un 422 plutôt qu'ignorés en silence.
attachments array — Objets avec filename, content_type, content en base64, et éventuellement cid pour les images en ligne.
language string — en ou fr. Définit la langue du pied de page que nous ajoutons.

L'adresse from est définie sur la clé, non dans la requête : une clé divulguée ne peut donc pas envoyer au nom d'un autre.

# Envoyer un message
curl -X POST https://zedmail.com/v1/email/send \
  -H "Authorization: Bearer $ZEDMAIL_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-18472-receipt" \
  -d '{
    "to": "jane@example.com",
    "subject": "Your receipt",
    "html": "<p>Thank you.</p>",
    "tags": ["receipt"]
  }'

=> 200
{ "status": "queued", "message_id": "msg_4f68af67910b67a097" }

État des messages

/v1/email/{id} répond à « qu'est-il arrivé à ce message ». /v1/recipients/{email} répond à « cette personne l'a-t-elle reçu », ce que le premier ne peut pas, car celui qui demande a rarement un identifiant de message.

Méthode Chemin Portée Fait
GET /v1/email/{id} email:messages.read Un message : état, horodatages, détail du rejet le cas échéant.
GET /v1/recipients/{email} email:messages.read Tout ce qui est connu d'une adresse, du plus récent au plus ancien. Paramètres limit et offset.

États

ÉtatSignifie
queuedAccepté, en attente de remise au serveur de messagerie. Quelques secondes — facile à manquer en test.
sentRemis, en attente d'un résultat. L'état normal en transit, et celui que vous verrez le plus. Résolu en quelques secondes d'ordinaire, mais un serveur destinataire qui diffère sans cesse peut retenir un message ici jusqu'à trois jours — ne traitez pas sent comme un échec.
deliveredLe serveur destinataire l'a accepté. Définitif.
bouncedRefusé comme non livrable; le destinataire est supprimé. Définitif.
blockedNon envoyé, car le chiffrement du transport n'a pu être assuré. L'adresse reste valide et n'est jamais supprimée. Définitif, mais vous pouvez réessayer une fois leur serveur corrigé.
complainedLe destinataire l'a marqué comme indésirable; il est supprimé. Définitif.

Seuls les quatre derniers sont définitifs. blocked est celui qu'on oublie : le message n'a pas été envoyé parce que le chiffrement du transport n'a pu être établi, donc l'adresse reste bonne.

Suppressions

Une adresse supprimée est refusée avant toute tentative d'envoi. Les raisons sont bounce, complaint, unsubscribe, manual et soft_bounce_threshold. Un message blocked ne crée jamais de suppression — l'adresse reste valide.

Méthode Chemin Portée Fait
GET /v1/suppressions email:suppressions.read Lister. Paramètres reason, page, per_page.
POST /v1/suppressions email:suppressions.write Ajouter. email et reason.
DELETE /v1/suppressions/{email} email:suppressions.write Retirer. Les plaintes et certaines lignes verrouillées sont réservées à l'opérateur et ne seront pas retirées.
POST /v1/suppressions/import email:suppressions.write Importation en masse.

Webhooks

Ces routes gèrent les points de terminaison. Les charges utiles, le schéma de signature et le calendrier des nouvelles tentatives sont documentés sur la page Webhooks de votre compte, où les exemples peuvent nommer vos propres points de terminaison et votre secret.

Méthode Chemin Portée Fait
GET /v1/webhooks email:webhooks.read Lister les points de terminaison.
POST /v1/webhooks email:webhooks.write Créer. url (HTTPS) et events.
PUT /v1/webhooks/{id} email:webhooks.write Modifier url, events ou is_active.
DELETE /v1/webhooks/{id} email:webhooks.write Supprimer.
POST /v1/webhooks/{id}/test email:webhooks.write Envoyer une livraison de test à ce point de terminaison.

Domaines d'envoi

Vous ne pouvez envoyer que depuis un domaine que vous avez vérifié. La vérification contrôle DKIM, SPF et DMARC comme un destinataire les lit.

Méthode Chemin Portée Fait
GET /v1/domains email:domains.read Lister les domaines et leur état de vérification.
POST /v1/domains email:domains.write Ajouter. domain. Retourne les enregistrements DNS à publier.
GET /v1/domains/{id} email:domains.read Un domaine, avec chaque enregistrement et s'il résout actuellement.
POST /v1/domains/{id}/verify email:domains.write Revérifier le DNS maintenant.
DELETE /v1/domains/{id} email:domains.write Retirer.

Statistiques et compte

Les paramètres from et to acceptent AAAA-MM-JJ. Les trois routes /v1/account/* reprennent la forme de leurs équivalents chez Amazon SES, pour qu'une migration conserve ses appels existants.

Méthode Chemin Portée Fait
GET /v1/stats email:stats.read Envoyés, livrés, rejetés, plaintes sur une période.
GET /v1/stats/bounces email:stats.read Rejets, avec type et code.
GET /v1/stats/complaints email:stats.read Plaintes.
GET /v1/account/quota email:stats.read Limite d'envoi quotidienne et ce qu'il en reste.
GET /v1/account/sending email:stats.read Si l'envoi est activé, en pause ou en bac à sable.
GET /v1/account/statistics email:stats.read Compteurs glissants.

Équipe

Invitations et membres. Les routes /invites sont déclarées avant /{id} et les identifiants sont contraints en UUID, de sorte que le segment littéral invites ne peut jamais être lu comme un identifiant d'utilisateur.

Méthode Chemin Portée Fait
GET /v1/users iam:users.read Lister les membres.
GET /v1/users/{id} iam:users.read Un membre.
PATCH /v1/users/{id} iam:users.write Changer un rôle. role.
DELETE /v1/users/{id} iam:users.write Retirer un membre.
GET /v1/users/invites iam:users.read Lister les invitations en cours.
POST /v1/users/invites iam:users.write Inviter quelqu'un. email et role.
DELETE /v1/users/invites/{id} iam:users.write Révoquer une invitation.

Bac à sable

Un nouveau compte n'envoie qu'aux adresses qu'il a vérifiées. Ceci en ajoute une.

Méthode Chemin Portée Fait
POST /v1/sandbox/recipients email:sandbox.write Ajouter un destinataire de test. email. Une confirmation leur est envoyée.

Ailleurs

Quelque chose manque ou est inexact ici ? Dites-le-nous et ce sera corrigé — cette page est vérifiée contre le routeur à chaque déploiement, mais seul le code dit ce qu'il fait.