Skip to content

Messages ​

Les routes sont relatives à <PUBLIC_BASE_URL> ; les corps de requête et de réponse sont en JSON sauf mention contraire. L’authentification, les portées, la pagination et le format des erreurs sont décrits dans les guides de l’API REST.

GET /api/v1/messages ​

Lister les messages du miroir

La vue à plat du miroir, les plus récents d’abord (pas la boîte par fils), paginée par curseur. q cherche l’objet, l’aperçu et l’expéditeur, avec la même grammaire que GET /api/v1/threads, et ne sort jamais des boîtes du membre.

Accès — Session de membre ou clé d’API portant messages:read.

Paramètres

NomOùTypeRequis
mailboxIdrequêtestringnon
cursorrequêtestringnon
limitrequêteintegernon
qrequêtestringnon

Réponses

200 — Une page de messages.

ChampTypeRequis
messagesobject[]oui
nextCursorstring | nulloui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "messages": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "mailboxId": { "type": "string" },
          "from": {
            "anyOf": [
              {
                "type": "object",
                "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
                "required": [ "email" ],
                "additionalProperties": false
              },
              { "type": "null" }
            ]
          },
          "subject": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
          "snippet": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
          "receivedAt": { "type": "string" },
          "folderLabels": { "type": "array", "items": { "type": "string" } },
          "flags": {
            "type": "object",
            "properties": {
              "seen": { "type": "boolean" },
              "flagged": { "type": "boolean" },
              "draft": { "type": "boolean" },
              "sent": { "type": "boolean" }
            },
            "required": [ "seen", "flagged", "draft", "sent" ],
            "additionalProperties": false
          },
          "signals": {
            "type": "object",
            "properties": {
              "isAutoReply": { "type": "boolean" },
              "isNoReply": { "type": "boolean" },
              "isMailingList": { "type": "boolean" },
              "isFromSelf": { "type": "boolean" }
            },
            "required": [ "isAutoReply", "isNoReply", "isMailingList", "isFromSelf" ],
            "additionalProperties": false
          },
          "hasAttachments": { "type": "boolean" }
        },
        "required": [
          "id",
          "mailboxId",
          "from",
          "subject",
          "snippet",
          "receivedAt",
          "folderLabels",
          "flags",
          "signals",
          "hasAttachments"
        ],
        "additionalProperties": false
      }
    },
    "nextCursor": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
  },
  "required": [ "messages", "nextCursor" ],
  "additionalProperties": false
}

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Codes d’erreur — request.bad_request. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

GET /api/v1/messages/{id} ​

Lire un message

Le message complet : en-têtes, destinataires, liste des pièces jointes et bodyHtmlSafe, assaini à chaque appel et jamais stocké. Ce HTML se rend dans une iframe sandboxée, jamais en ligne.

Accès — Session de membre ou clé d’API portant messages:read.

Paramètres

NomOùTypeRequis
idcheminstring (uuid)oui

Réponses

200 — Le message.

ChampTypeRequis
idstringoui
mailboxIdstringoui
fromobject | nulloui
subjectstring | nulloui
snippetstring | nulloui
receivedAtstringoui
folderLabelsstring[]oui
flagsobjectoui
signalsobjectoui
hasAttachmentsbooleanoui
threadIdstring | nulloui
classificationobjectoui
bodyTextstring | nulloui
bodyHtmlSafestring | nulloui
hasRemoteImagesbooleanoui
bodyCompletebooleanoui
headersSubsetobjectoui
attachmentsobject[]oui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "id": { "type": "string" },
    "mailboxId": { "type": "string" },
    "from": {
      "anyOf": [
        {
          "type": "object",
          "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
          "required": [ "email" ],
          "additionalProperties": false
        },
        { "type": "null" }
      ]
    },
    "subject": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
    "snippet": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
    "receivedAt": { "type": "string" },
    "folderLabels": { "type": "array", "items": { "type": "string" } },
    "flags": {
      "type": "object",
      "properties": {
        "seen": { "type": "boolean" },
        "flagged": { "type": "boolean" },
        "draft": { "type": "boolean" },
        "sent": { "type": "boolean" }
      },
      "required": [ "seen", "flagged", "draft", "sent" ],
      "additionalProperties": false
    },
    "signals": {
      "type": "object",
      "properties": {
        "isAutoReply": { "type": "boolean" },
        "isNoReply": { "type": "boolean" },
        "isMailingList": { "type": "boolean" },
        "isFromSelf": { "type": "boolean" }
      },
      "required": [ "isAutoReply", "isNoReply", "isMailingList", "isFromSelf" ],
      "additionalProperties": false
    },
    "hasAttachments": { "type": "boolean" },
    "threadId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
    "classification": {
      "type": "object",
      "propertyNames": { "type": "string" },
      "additionalProperties": {}
    },
    "bodyText": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
    "bodyHtmlSafe": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
    "hasRemoteImages": { "type": "boolean" },
    "bodyComplete": { "type": "boolean" },
    "headersSubset": {
      "type": "object",
      "properties": {
        "to": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
            "required": [ "email" ],
            "additionalProperties": false
          }
        },
        "cc": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
            "required": [ "email" ],
            "additionalProperties": false
          }
        },
        "replyTo": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
            "required": [ "email" ],
            "additionalProperties": false
          }
        },
        "date": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
        "messageIdHeader": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
      },
      "required": [ "to", "cc", "replyTo", "date", "messageIdHeader" ],
      "additionalProperties": false
    },
    "attachments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "position": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
          "filename": { "type": "string" },
          "mime": { "type": "string" },
          "size": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
          "disposition": { "type": "string", "enum": [ "attachment", "inline" ] },
          "contentId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
          "downloadUrl": { "type": "string" }
        },
        "required": [
          "id",
          "position",
          "filename",
          "mime",
          "size",
          "disposition",
          "contentId",
          "downloadUrl"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "id",
    "mailboxId",
    "from",
    "subject",
    "snippet",
    "receivedAt",
    "folderLabels",
    "flags",
    "signals",
    "hasAttachments",
    "threadId",
    "classification",
    "bodyText",
    "bodyHtmlSafe",
    "hasRemoteImages",
    "bodyComplete",
    "headersSubset",
    "attachments"
  ],
  "additionalProperties": false
}

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Codes d’erreur — request.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

GET /api/v1/messages/{id}/attachments/{position} ​

Télécharger une pièce jointe

Les octets bruts de la pièce à ce rang MIME, servis en téléchargement (Content-Disposition: attachment, nosniff, no-store). Les types actifs (HTML, SVG, scripts) sont forcés en application/octet-stream. Hors périmètre, rang inexistant ou objet purgé : un seul et même 404.

Accès — Session de membre ou clé d’API portant messages:read.

Paramètres

NomOùTypeRequis
idcheminstring (uuid)oui
positioncheminintegeroui

Réponses

200 — Le fichier.

Type de contenu : application/octet-stream

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Codes d’erreur — request.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

GET /api/v1/messages/{id}/journal ​

Le « pourquoi » d’un message

L’entrée de journal d’un message et les exécutions qu’il a lancées.

Accès — Session de membre ou clé d’API portant messages:read.

Paramètres

NomOùTypeRequis
idcheminstring (uuid)oui

Réponses

200 — L’entrée et ses exécutions.

ChampTypeRequis
entryobject | nulloui
executionsobject[]oui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "entry": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "id": { "type": "string" },
            "outcome": {
              "type": "string",
              "enum": [
                "excluded_org",
                "excluded_member",
                "guardrail",
                "unmatched",
                "dispatched"
              ]
            },
            "ruleRef": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
            "createdAt": { "type": "string" }
          },
          "required": [ "id", "outcome", "ruleRef", "createdAt" ],
          "additionalProperties": false
        },
        { "type": "null" }
      ]
    },
    "executions": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "workflowId": { "type": "string" },
          "workflowName": { "type": "string" },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "waiting",
              "succeeded",
              "failed",
              "cancelled"
            ]
          },
          "simulated": { "type": "boolean" },
          "createdAt": { "type": "string" },
          "finishedAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
        },
        "required": [
          "id",
          "workflowId",
          "workflowName",
          "status",
          "simulated",
          "createdAt",
          "finishedAt"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [ "entry", "executions" ],
  "additionalProperties": false
}

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Codes d’erreur — request.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

POST /api/v1/messages/send ​

Envoyer un message

Compose et enfile un message depuis une des boîtes du membre. Rien ne part de manière synchrone : la réponse porte l’opId de l’opération sortante et le miroir ramène l’état réel au delta suivant. clientToken est obligatoire et déduplique : un rejeu rend 202 { duplicate: true } avec la même opId. Les pièces jointes sont des références téléversées auparavant. Soumis au kill switch d’envoi (403) et au débit par boîte (429, avec Retry-After et retryAfterMs).

Accès — Session de membre ou clé d’API portant messages:write.

Corps de la requête (application/json)

ChampTypeRequis
mailboxIdstringoui
tostring (email)[]oui
ccstring (email)[]non
bccstring (email)[]non
subjectstringoui
bodyTextstringoui
bodyHtmlstringnon
replyToMessageIdstringnon
forwardOfMessageIdstringnon
includeOriginalAttachmentsbooleannon
quoteOriginalbooleannon
attachmentsobject[]non
clientTokenstringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "mailboxId": { "type": "string", "minLength": 1 },
    "to": {
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "cc": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "bcc": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "subject": { "type": "string", "maxLength": 512 },
    "bodyText": { "type": "string", "maxLength": 200000 },
    "bodyHtml": { "type": "string", "maxLength": 500000 },
    "replyToMessageId": { "type": "string", "minLength": 1 },
    "forwardOfMessageId": { "type": "string", "minLength": 1 },
    "includeOriginalAttachments": { "type": "boolean" },
    "quoteOriginal": { "type": "boolean" },
    "attachments": {
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "attachmentId": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9._-]+$"
          }
        },
        "required": [ "attachmentId" ]
      }
    },
    "clientToken": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._:-]+$"
    }
  },
  "required": [ "mailboxId", "to", "subject", "bodyText", "clientToken" ]
}

Réponses

202 — Enfilé.

ChampTypeRequis
opIdstringoui
kind"send" | "draft"oui
duplicatebooleanoui
threadIdstring | nulloui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "opId": { "type": "string" },
    "kind": { "type": "string", "enum": [ "send", "draft" ] },
    "duplicate": { "type": "boolean" },
    "threadId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
  },
  "required": [ "opId", "kind", "duplicate", "threadId" ],
  "additionalProperties": false
}

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.mailbox_not_found, webmail.message_not_found, webmail.attachment_not_found, webmail.message_too_large, webmail.sending_disabled, webmail.rate_limited. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

Exemple de requête

json
{
  "mailboxId": "0192f1c2-3b4d-7e8f-9a0b-1c2d3e4f5a6b",
  "to": [ "bob@example.test" ],
  "subject": "Quote #1042",
  "bodyText": "Hello Bob,\n\nPlease find the quote attached.\n\nAlice",
  "attachments": [ { "attachmentId": "0192f1c2-0000-7000-8000-00000000a7a7" } ],
  "clientToken": "b2c7e4a0-9f3d-4c1e-8a6b-5d2f1e0c9b8a"
}

Exemple de réponse (202)

json
{
  "opId": "0192f1c2-0000-7000-8000-0000000000aa",
  "kind": "send",
  "duplicate": false,
  "threadId": null
}

POST /api/v1/messages/drafts ​

Créer un brouillon

Le même corps que /send, enregistré en brouillon chez le fournisseur. Ni kill switch ni débit : un brouillon ne part pas. Un clientToken rejoué est un doublon, pas une réécriture — PUT réécrit.

Accès — Session de membre ou clé d’API portant messages:write.

Corps de la requête (application/json)

ChampTypeRequis
mailboxIdstringoui
tostring (email)[]oui
ccstring (email)[]non
bccstring (email)[]non
subjectstringoui
bodyTextstringoui
bodyHtmlstringnon
replyToMessageIdstringnon
forwardOfMessageIdstringnon
includeOriginalAttachmentsbooleannon
quoteOriginalbooleannon
attachmentsobject[]non
clientTokenstringoui

Même schéma que POST /api/v1/messages/send.

Réponses

202 — Enfilé.

ChampTypeRequis
opIdstringoui
kind"send" | "draft"oui
duplicatebooleanoui
threadIdstring | nulloui

Même schéma que POST /api/v1/messages/send.

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.mailbox_not_found, webmail.message_not_found, webmail.attachment_not_found, webmail.message_too_large. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

PUT /api/v1/messages/drafts ​

Enregistrer un brouillon (autosave)

Réécrit le brouillon identifié par clientToken : le contenu déjà enregistré sous ce jeton est remplacé, donc une session de composition produit UN brouillon quel que soit le nombre de sauvegardes. savedAt est l’heure de cette sauvegarde. Ni kill switch ni débit.

Accès — Session de membre ou clé d’API portant messages:write.

Corps de la requête (application/json)

ChampTypeRequis
mailboxIdstringoui
tostring (email)[]oui
ccstring (email)[]non
bccstring (email)[]non
subjectstringoui
bodyTextstringoui
bodyHtmlstringnon
replyToMessageIdstringnon
forwardOfMessageIdstringnon
includeOriginalAttachmentsbooleannon
quoteOriginalbooleannon
attachmentsobject[]non
clientTokenstringoui

Même schéma que POST /api/v1/messages/send.

Réponses

202 — Enfilé.

ChampTypeRequis
opIdstringoui
kind"send" | "draft"oui
duplicatebooleanoui
threadIdstring | nulloui
savedAtstringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "opId": { "type": "string" },
    "kind": { "type": "string", "enum": [ "send", "draft" ] },
    "duplicate": { "type": "boolean" },
    "threadId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
    "savedAt": { "type": "string" }
  },
  "required": [ "opId", "kind", "duplicate", "threadId", "savedAt" ],
  "additionalProperties": false
}

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Codes d’erreur — webmail.bad_request, webmail.mailbox_not_found, webmail.message_not_found, webmail.attachment_not_found, webmail.message_too_large. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

POST /api/v1/messages/attachments ​

Téléverser une pièce jointe

Un fichier par requête, en multipart, avant de composer : la réponse donne l’attachmentId à référencer dans attachments. Rend ce que l’instance a constaté (nom nettoyé, type normalisé, taille mesurée). Au-delà de 25 Mo, 413 ; exécutables et scripts, 400.

Accès — Session de membre ou clé d’API portant messages:write.

Corps de la requête (multipart/form-data)

ChampTypeRequisDescription
filestringouiThe file, as a binary multipart part.
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "file": { "type": "string", "description": "The file, as a binary multipart part." }
  },
  "required": [ "file" ]
}

Réponses

201 — La pièce enregistrée.

ChampTypeRequis
attachmentIdstringoui
filenamestringoui
sizeintegeroui
mimestringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "attachmentId": { "type": "string" },
    "filename": { "type": "string" },
    "size": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
    "mime": { "type": "string" }
  },
  "required": [ "attachmentId", "filename", "size", "mime" ],
  "additionalProperties": false
}

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.attachment_too_large, webmail.attachment_rejected. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

POST /api/v1/messages/{id}/forward ​

Transférer un message

Un raccourci sur /send : les pièces d’origine sont re-référencées par l’instance (sans re-téléversement), l’objet reçoit Fwd:, la chaîne References est conservée sans In-Reply-To. Même kill switch et même débit qu’un envoi.

Accès — Session de membre ou clé d’API portant messages:write.

Paramètres

NomOùTypeRequis
idcheminstringoui

Corps de la requête (application/json)

ChampTypeRequis
tostring (email)[]oui
ccstring (email)[]non
bccstring (email)[]non
subjectstringnon
bodyTextstringoui
bodyHtmlstringnon
includeOriginalAttachmentsbooleannon
quoteOriginalbooleannon
attachmentsobject[]non
asDraftbooleannon
clientTokenstringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "to": {
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "cc": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "bcc": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "subject": { "type": "string", "maxLength": 512 },
    "bodyText": { "type": "string", "maxLength": 200000 },
    "bodyHtml": { "type": "string", "maxLength": 500000 },
    "includeOriginalAttachments": { "type": "boolean" },
    "quoteOriginal": { "type": "boolean" },
    "attachments": {
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "attachmentId": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9._-]+$"
          }
        },
        "required": [ "attachmentId" ]
      }
    },
    "asDraft": { "type": "boolean" },
    "clientToken": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._:-]+$"
    }
  },
  "required": [ "to", "bodyText", "clientToken" ]
}

Réponses

202 — Enfilé.

ChampTypeRequis
opIdstringoui
kind"send" | "draft"oui
duplicatebooleanoui
threadIdstring | nulloui

Même schéma que POST /api/v1/messages/send.

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.mailbox_not_found, webmail.message_not_found, webmail.attachment_not_found, webmail.message_too_large, webmail.sending_disabled, webmail.rate_limited. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

POST /api/v1/messages/{id}/reply ​

Répondre à un message

Un raccourci sur /send : boîte, destinataires, objet et fil sont pré-résolus depuis l’original, puis exactement le même chemin qu’un envoi — aucune réponse ne contourne le kill switch ni le débit.

Accès — Session de membre ou clé d’API portant messages:write.

Paramètres

NomOùTypeRequis
idcheminstringoui

Corps de la requête (application/json)

ChampTypeRequis
tostring (email)[]non
ccstring (email)[]non
bccstring (email)[]non
subjectstringnon
bodyTextstringoui
bodyHtmlstringnon
asDraftbooleannon
attachmentsobject[]non
clientTokenstringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "to": {
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "cc": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "bcc": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 320,
        "format": "email",
        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "subject": { "type": "string", "maxLength": 512 },
    "bodyText": { "type": "string", "maxLength": 200000 },
    "bodyHtml": { "type": "string", "maxLength": 500000 },
    "asDraft": { "type": "boolean" },
    "attachments": {
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "attachmentId": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9._-]+$"
          }
        },
        "required": [ "attachmentId" ]
      }
    },
    "clientToken": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._:-]+$"
    }
  },
  "required": [ "bodyText", "clientToken" ]
}

Réponses

202 — Enfilé.

ChampTypeRequis
opIdstringoui
kind"send" | "draft"oui
duplicatebooleanoui
threadIdstring | nulloui

Même schéma que POST /api/v1/messages/send.

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.mailbox_not_found, webmail.message_not_found, webmail.attachment_not_found, webmail.message_too_large, webmail.sending_disabled, webmail.rate_limited. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

POST /api/v1/messages/{id}/actions ​

Agir sur un message

Archiver, marquer lu ou non lu, suivre, classer, mettre à la corbeille… La réponse dit que l’opération est enregistrée, pas que l’état a changé : le miroir le ramène au delta suivant. Les gestes que le fournisseur ne sait pas faire (suppression définitive chez Gmail) sont refusés avant d’enfiler.

Accès — Session de membre ou clé d’API portant messages:write.

Paramètres

NomOùTypeRequis
idcheminstringoui

Corps de la requête (application/json)

ChampTypeRequis
actionstring (enum)oui
labelsobjectnon
clientTokenstringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": [
        "markRead",
        "markUnread",
        "flag",
        "unflag",
        "archive",
        "unarchive",
        "trash",
        "restore",
        "spam",
        "notSpam",
        "deletePermanently",
        "move"
      ]
    },
    "labels": {
      "type": "object",
      "properties": {
        "add": {
          "maxItems": 20,
          "type": "array",
          "items": { "type": "string", "minLength": 1, "maxLength": 200 }
        },
        "remove": {
          "maxItems": 20,
          "type": "array",
          "items": { "type": "string", "minLength": 1, "maxLength": 200 }
        }
      }
    },
    "clientToken": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._:-]+$"
    }
  },
  "required": [ "action", "clientToken" ]
}

Réponses

202 — Les opérations enfilées.

ChampTypeRequis
opsobject[]oui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "ops": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "messageId": { "type": "string" },
          "opId": { "type": "string" },
          "duplicate": { "type": "boolean" }
        },
        "required": [ "messageId", "opId", "duplicate" ],
        "additionalProperties": false
      }
    }
  },
  "required": [ "ops" ],
  "additionalProperties": false
}

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.message_not_found, webmail.unsupported_action. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.

POST /api/v1/messages/actions ​

Agir sur plusieurs messages

La même action sur au plus 100 messages, tout ou rien sur le périmètre : un seul identifiant hors des boîtes du membre rend 404 et rien n’est enfilé.

Accès — Session de membre ou clé d’API portant messages:write.

Corps de la requête (application/json)

ChampTypeRequis
messageIdsstring[]oui
actionstring (enum)oui
labelsobjectnon
clientTokenstringoui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "messageIds": {
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": { "type": "string", "minLength": 1 }
    },
    "action": {
      "type": "string",
      "enum": [
        "markRead",
        "markUnread",
        "flag",
        "unflag",
        "archive",
        "unarchive",
        "trash",
        "restore",
        "spam",
        "notSpam",
        "deletePermanently",
        "move"
      ]
    },
    "labels": {
      "type": "object",
      "properties": {
        "add": {
          "maxItems": 20,
          "type": "array",
          "items": { "type": "string", "minLength": 1, "maxLength": 200 }
        },
        "remove": {
          "maxItems": 20,
          "type": "array",
          "items": { "type": "string", "minLength": 1, "maxLength": 200 }
        }
      }
    },
    "clientToken": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._:-]+$"
    }
  },
  "required": [ "messageIds", "action", "clientToken" ]
}

Réponses

202 — Les opérations enfilées.

ChampTypeRequis
opsobject[]oui

Même schéma que POST /api/v1/messages/{id}/actions.

400 — La requête ne respecte pas son schéma.

401 — Aucune session ni clé d’API valide (auth.unauthenticated).

403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).

429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.

Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.

Codes d’erreur — webmail.bad_request, webmail.message_not_found, webmail.unsupported_action. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.