Skip to content

Fils ​

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/threads ​

Lister les fils

La boîte de réception, par conversation, paginée par curseur. Deux axes orthogonaux se combinent : folder (défaut inbox ; all exclut corbeille et spam) et filter (non lus, suivis, avec pièces jointes). q cherche dans le dossier courant ; searchEverywhere élargit à tous les dossiers, corbeille et spam compris. Une clé de dossier inconnue rend 400.

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

Paramètres

NomOùTypeRequis
mailboxIdrequêtestringnon
cursorrequêtestringnon
limitrequêteintegernon
qrequêtestringnon
filterrequête"all" | "unread" | "flagged" | "attachments"non
folderrequêtestringnon
searchEverywhererequêtebooleannon

Réponses

200 — Une page de fils.

ChampTypeRequis
threadsobject[]oui
nextCursorstring | nulloui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "threads": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "mailboxId": { "type": "string" },
          "subject": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
          "lastMessageAt": { "type": "string" },
          "messageCount": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "unreadCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
          "participants": {
            "maxItems": 3,
            "type": "array",
            "items": {
              "type": "object",
              "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
              "required": [ "email" ],
              "additionalProperties": false
            }
          },
          "participantCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
          "snippet": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
          "hasAttachments": { "type": "boolean" },
          "flags": {
            "type": "object",
            "properties": {
              "seen": { "type": "boolean" },
              "flagged": { "type": "boolean" },
              "draft": { "type": "boolean" },
              "sent": { "type": "boolean" }
            },
            "required": [ "seen", "flagged", "draft", "sent" ],
            "additionalProperties": false
          },
          "classification": {
            "type": "object",
            "propertyNames": { "type": "string" },
            "additionalProperties": {}
          }
        },
        "required": [
          "id",
          "mailboxId",
          "subject",
          "lastMessageAt",
          "messageCount",
          "unreadCount",
          "participants",
          "participantCount",
          "snippet",
          "hasAttachments",
          "flags",
          "classification"
        ],
        "additionalProperties": false
      }
    },
    "nextCursor": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
  },
  "required": [ "threads", "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/threads/{id} ​

Lire un fil

La conversation entière dans l’ordre de lecture, avec le corps assaini de chaque message. Un fil hors des boîtes du membre rend le même 404 qu’un fil inexistant.

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

Paramètres

NomOùTypeRequis
idcheminstring (uuid)oui

Réponses

200 — Le fil.

ChampTypeRequis
threadobjectoui
messagesobject[]oui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "thread": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "mailboxId": { "type": "string" },
        "subject": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
        "lastMessageAt": { "type": "string" },
        "messageCount": {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        "unreadCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
        "participants": {
          "maxItems": 3,
          "type": "array",
          "items": {
            "type": "object",
            "properties": { "name": { "type": "string" }, "email": { "type": "string" } },
            "required": [ "email" ],
            "additionalProperties": false
          }
        },
        "participantCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
        "snippet": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
        "hasAttachments": { "type": "boolean" },
        "flags": {
          "type": "object",
          "properties": {
            "seen": { "type": "boolean" },
            "flagged": { "type": "boolean" },
            "draft": { "type": "boolean" },
            "sent": { "type": "boolean" }
          },
          "required": [ "seen", "flagged", "draft", "sent" ],
          "additionalProperties": false
        },
        "classification": {
          "type": "object",
          "propertyNames": { "type": "string" },
          "additionalProperties": {}
        }
      },
      "required": [
        "id",
        "mailboxId",
        "subject",
        "lastMessageAt",
        "messageCount",
        "unreadCount",
        "participants",
        "participantCount",
        "snippet",
        "hasAttachments",
        "flags",
        "classification"
      ],
      "additionalProperties": false
    },
    "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
      }
    }
  },
  "required": [ "thread", "messages" ],
  "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/threads/{id}/actions ​

Agir sur tout un fil

Les messages du fil sont résolus par l’instance au moment de l’appel : un message arrivé après l’affichage est inclus. Une opération par message. Un fil de 1000 messages ou plus est refusé plutôt que tronqué.

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
threadIdstringoui
opsobject[]oui
Schéma JSON
json
{
  "type": "object",
  "properties": {
    "threadId": { "type": "string" },
    "ops": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "messageId": { "type": "string" },
          "opId": { "type": "string" },
          "duplicate": { "type": "boolean" }
        },
        "required": [ "messageId", "opId", "duplicate" ],
        "additionalProperties": false
      }
    }
  },
  "required": [ "threadId", "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.thread_not_found, webmail.thread_too_large, 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.