Trois points d'accès, JSON en entrée et en sortie. Ni clé ni compte sur les domaines publics — collez une requête dans un terminal et ça fonctionne.
Vue d'ensemble
Une boîte n'est jamais créée — elle existe dès qu'un message arrive à une adresse, et disparaît 5 jours plus tard. Il n'y a rien à enregistrer, donc sur les domaines publics l'API ne connaît ni utilisateur, ni projet, ni jeton.
Chaque réponse est du JSON, y compris chaque erreur.
Toutes les heures sont en UTC au format RFC 3339 — 2026-08-04T18:31:07Z.
Les identifiants de message sont des chaînes opaques. Ne les analysez pas.
Réception uniquement. Il n'existe volontairement aucun point d'accès pour envoyer du courrier.
URL de base
https://grabmail.io/api/v1
HTTPS uniquement ; le HTTP simple est redirigé. La version figure dans le chemin, et v1 ne changera pas de forme sous vos pieds — un changement incompatible reçoit un nouveau numéro.
Authentification : aucune
Aucune, sur les domaines publics. Quiconque connaît une adresse peut lire sa boîte, aussi bien via l'API que via le site. C'est le compromis que fait tout service jetable partagé : ne confiez jamais à une adresse publique quelque chose auquel vous tenez.
Un domaine que vous pointez ici répond sur ces mêmes points d'accès, sans
clé non plus. Pointez le MX vers nous et le premier message le connecte ; voir
connexion d'un domaine. Les boîtes qu'il contient sont lisibles par quiconque connaît l'adresse,
exactement comme les domaines publics.
Un seul cas garde un en-tête : un domaine que nous avons fermé sur demande se
lit avec Authorization: Bearer <key>, et une clé manquante ou
incorrecte répond 401 avec unauthorized. Les clés
sont comparées en temps constant : rejeter une mauvaise en prend autant que
d'accepter une bonne.
Domaines premium
La seule exception à la règle ci-dessus. Les domaines publics
figurent sur les listes publiques de messagerie jetable, et c'est pourquoi un formulaire
d'inscription refuse parfois une adresse qui s'y trouve. Un plan payant ouvre un pool de
92 domaines .com privés, hors de ces listes.
L'API ne change en rien. Mêmes chemins, mêmes paramètres, mêmes formes de réponse. La seule différence tient dans un en-tête : une adresse premium se lit avec Authorization: Bearer gm_live_…, avec une clé issue de vos clés d'API. Sans clé valable, la même requête répond 402 ou 403 — jamais une boîte.
# A public domain: no header at all.
curl -sG https://grabmail.io/api/v1/mailbox \
--data-urlencode "address=a7f3k2@grabmail.io"
# A premium domain: the same call, plus a key.
curl -sG https://grabmail.io/api/v1/mailbox \
-H "Authorization: Bearer gm_live_…" \
--data-urlencode "address=a7f3k2@one-of-the-pool.com"
Les domaines publics et vos propres domaines restent gratuits, sans clé et sans limite sur tous les plans, y compris le gratuit. Les quotas ne comptent que les messages arrivant sur le pool premium. Les plans et les prix sont sur la page des plans.
Points d'accès
GET/api/v1/mailbox
Tout ce qui attend à une adresse, du plus récent au plus ancien. C'est l'appel que votre suite de tests interroge en boucle.
Paramètres
Nom
Entrée
Type
Requis
Description
address
query
string
oui
La boîte à lire, par ex. k7fq2m@grabmail.io.
limit
query
integer
non
Nombre de messages à renvoyer pour cet appel, 1–200. Par défaut 50, du plus récent au plus ancien. Cela limite une réponse, pas la boîte — utilisez before pour lire au-delà.
before
query
string
non
L'id du message le plus ancien que vous avez déjà ; renvoie la page suivante. Repassez le champ next de la réponse précédente. Quand next vaut null, vous avez tout.
Supprimé. L'appel est idempotent : supprimer deux fois répond quand même 200.
400
mailbox est manquant ou invalide.
404
Aucun message de ce type dans cette boîte.
429
Limite de débit dépassée.
Pièces jointes
Chaque message liste ses pièces jointes avec une URL prête à l'emploi. Récupérez-la avec la même autorisation que le message lui-même.
GET /api/v1/attachment/{id}?mailbox={address}
Elle répond toujours application/octet-stream avec Content-Disposition: attachment, quelle que soit l'étiquette donnée par l'expéditeur. C'est volontaire : renvoyer tel quel un text/html d'inconnu permettrait à une pièce jointe de s'exécuter comme une page sur cette origine. Le vrai type figure dans le JSON du message, où il est une donnée et non une instruction.
Erreurs
Chaque échec est un JSON avec les deux mêmes champs, pour qu'un client les traite en un seul endroit. Le statut porte la catégorie, error est un identifiant stable destiné aux machines, et message est destiné aux humains et peut être reformulé à tout moment.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_address",
"message": "address must look like name@domain"
}
Ne conditionnez jamais votre logique à message. Les identifiants utilisés sont invalid_address, unknown_domain, not_found et rate_limited.
Limites de débit
Une requête par seconde, par adresse. Interroger une boîte une fois par seconde est le comportement prévu et n'est jamais limité.
Au-delà de la limite, vous obtenez 429 avec Retry-After en secondes. Il n'y a ni quota journalier ni crédit de rafale à gérer.
Rétention
Un message est supprimé 5 jours après son arrivée, lu ou non. Chaque message porte expires_at, vous n'avez donc jamais à calculer cette date vous-même.
C'est une limite fixe, pas un réglage — aucun paramètre ne l'étend. Si un message doit survivre à la fenêtre, récupérez-le et stockez-le de votre côté.
Votre propre domaine
Pointez votre MX vers smtp.grabmail.io et chaque adresse de
votre domaine répond via ces mêmes points d'accès — pas de seconde API à apprendre,
pas d'inscription, pas de clé.