Три эндпоинта, JSON на входе и на выходе. Без ключа и без аккаунта на публичных
доменах — вставьте запрос в терминал, и он сработает.
Обзор
Почтовый ящик никогда не создаётся — он появляется в момент, когда на адрес
приходит письмо, и исчезает через 5 дней. Регистрировать
нечего, поэтому на публичных доменах у API нет понятия пользователя,
проекта или токена.
Каждый ответ — это JSON, включая любую ошибку.
Всё время указано в UTC в формате RFC 3339 — 2026-08-04T18:31:07Z.
ID сообщений — непрозрачные строки. Не разбирайте их.
Только приём. Эндпоинта для отправки почты нет — так и задумано.
Базовый URL
https://grabmail.io/api/v1
Только HTTPS; обычный HTTP перенаправляется. Версия указана в пути, и
v1 не изменит свою форму у вас под ногами — для несовместимого
изменения будет использован новый номер.
Аутентификация: не требуется
Никакой — на публичных доменах. Любой, кто знает адрес, может
прочитать его почтовый ящик — через API точно так же, как через сайт. Таковы
условия общего одноразового сервиса, поэтому никогда не направляйте на
публичный адрес то, что вам дорого.
Домен, который вы направите сюда, отвечает на те же эндпоинты, тоже
без ключа. Направьте MX на нас, и первое же письмо подключит домен; см.
подключение домена. Ящики на нём читает любой, кто знает адрес, —
точно так же, как на публичных доменах.
Единственные учётные данные в этом API — ключ вашего аккаунта, описанный ниже: один у бесплатного аккаунта, больше на платных тарифах. У ключа нет собственного уровня: каждый вызов оценивается по тарифу, который у его аккаунта в этот момент, поэтому тот же ключ теряет бесплатные ограничения и открывает премиум-пул, как только вы оформляете подписку, и возвращается к бесплатному лимиту, когда тариф заканчивается. Публичным доменам ключ не нужен; отправленный с ними, он засчитывает ваши вызовы вашему аккаунту, а не IP-адресу. Ключ, который отправлен, но неизвестен или отозван, отвечает 401 с unauthorized на любом эндпоинте, независимо от домена — так опечатка в ключе видна сразу, а не выглядит как пустой ящик.
Премиум-домены
Единственное исключение из правила выше. Публичные домены
входят в публичные списки одноразовой почты — именно поэтому форма регистрации
иногда отклоняет адрес на них. Платный тариф открывает пул из
97 частных доменов .com, вне этих списков.
В API не меняется ничего. Те же пути, те же параметры, те же формы ответа. Единственное отличие — один заголовок: премиум-адрес читается с Authorization: Bearer gm_live_…, используя ключ из ваши API-ключи. Без ключа от платного тарифа тот же запрос отвечает 404 — слово в слово тот же ответ, что и для домена, который мы не обслуживаем, — намеренно, чтобы пул нельзя было раскрыть перебором имён. Никогда не ящик.
Где находятся домены пула
GET /api/v1/domains с вашим ключом возвращает публичные домены и доменные имена пула. Тот же вызов без ключа — или с ключом бесплатного или просроченного аккаунта — возвращает публичные домены, сколько доменов в пуле и сколько это стоит, но никогда не имя: за то, чтобы держать их вне чёрных списков одноразовой почты, и платит тариф. Вошедший в систему подписчик также видит пул в выборе доменов на главной странице.
GET /api/v1/me — единственный вызов, который оценивает ключ сам по себе: 200 с тарифом, текущим периодом, израсходованной и оставшейся квотой, удерживаемыми адресами и вашим лимитом запросов — либо 401unauthorized, если ключ неизвестен или отозван. Вызывайте его первым, если что-то в пуле отвечает 404: тот ответ намеренно скрывает проблему с ключом, а этот — показывает её.
Каждый случай и причина, по которой он происходит. Первые два — именно те, что выглядят неожиданно, пока не прочтёшь причину.
404
unknown_domain — ключа нет, либо ключ от бесплатного или просроченного аккаунта. Намеренно совпадает с ответом для домена, который мы не обслуживаем: если бы их можно было различить, пул можно было бы раскрыть перебором имён. Проверьте ключ через /api/v1/me.
401
unauthorized — отправленный ключ неизвестен или отозван. Возвращается на любом эндпоинте, независимо от домена: это сообщение о ключе, а не о домене.
402
quota_reached — квота за этот период исчерпана, а продолжение сверх квоты выключено. overage_cap / overage_funds — продолжение сверх квоты включено, но достигнут заданный вами потолок либо не хватает средств на балансе. Уже удерживаемые адреса продолжают работать во всех трёх случаях.
403
address_taken — этот адрес уже удерживает другой подписчик. Выберите другое имя.
409
address_limit — зарезервирован для тарифа с лимитом адресов. Сегодня такого тарифа нет.
429
rate_limited — на бесплатном тарифе (без ключа или с бесплатным ключом): больше 60 запросов в минуту или больше одного чтения в секунду на один адрес; с ключом платного тарифа: больше 2, 3 или 5 чтений в секунду на один адрес. daily_limit_reached — израсходованы все 1 000 бесплатных запросов за сутки. У платных тарифов нет ни поминутного, ни суточного лимита. Оба ответа содержат Retry-After.
Удерживаемые адреса и квота
Премиум-адрес удерживается первым аккаунтом, который прочитает его действующим ключом, — подойдёт любое чтение, на любом эндпоинте или через MCP, заранее резервировать ничего не нужно. Пока он удерживается, прочитать его может только этот аккаунт; все остальные получают 403. Он остаётся удерживаемым, пока вы не освободите его в панели, либо пока тариф не закончится — в дату окончания, без льготного периода.
Квота считает единицы: письмо, полученное на премиум-адрес, или открытый новый премиум-адрес — что наступит раньше, — поэтому адрес, который вы открыли и ни разу не прочли, всё равно расходует одну единицу. Повторное чтение уже удерживаемого адреса бесплатно. Ни один тариф не ограничивает число адресов, которые может удерживать аккаунт; ограничивает именно квота, а сколько её осталось, показывает /api/v1/me.
Алиас — и на премиум-адресах тоже
У каждого списка ящика есть alias: второй адрес, который доставляет в тот же ящик и ничего о нём не раскрывает. Отдайте алиас форме, а адрес опрашивайте; тот, у кого есть только алиас, всегда видит пустой ящик. Он стабилен для данного адреса, бесплатен и возвращается для премиум-адресов точно так же, как для публичных. Его домен — один из наших и намеренно нигде не публикуется.
Всё целиком — в четыре вызова
KEY="gm_live_…" # со страницы ваших API-ключей, по платному тарифу
# 1. Проверить ключ: тариф, остаток квоты, лимит запросов. 401, если ключ неверен.
curl -s https://grabmail.io/api/v1/me -H "Authorization: Bearer $KEY"
# 2. Получить список пула. Имена в ответе — только с платным ключом.
curl -s https://grabmail.io/api/v1/domains -H "Authorization: Bearer $KEY"
# 3. Прочитать ящик на одном из них. Это первое чтение закрепляет адрес и считается за одну единицу.
curl -sG https://grabmail.io/api/v1/mailbox -H "Authorization: Bearer $KEY" \
--data-urlencode "address=a7f3k2@one-of-the-pool.com"
# 4. Прочитать одно сообщение — тот же заголовок.
curl -sG https://grabmail.io/api/v1/message/MESSAGE_ID -H "Authorization: Bearer $KEY" \
--data-urlencode "mailbox=a7f3k2@one-of-the-pool.com"
Публичные домены и ваши собственные остаются бесплатными, без ключа и без ограничений на всех тарифах, включая бесплатный. Квота учитывает только премиум-пул и ничего больше. Тарифы и цены — на страница тарифов.
Эндпоинты
GET/api/v1/mailbox
Всё, что ждёт на адресе, сначала новые. Это тот самый вызов, который опрашивает ваш набор тестов.
Параметры
Имя
Вход
Тип
Обязательно
Описание
address
query
string
да
Ящик для чтения, например k7fq2m@grabmail.io.
limit
query
integer
нет
Сколько сообщений вернуть в этом вызове, 1–200. По умолчанию 50, сначала новые. Это ограничивает один ответ, а не ящик — используйте before, чтобы читать дальше.
before
query
string
нет
id самого старого сообщения, которое у вас уже есть; возвращает страницу после него. Передайте обратно поле next из предыдущего ответа. Когда next равно null, у вас есть всё.
Ящик прочитан. Пустой ящик — это 200 с count: 0, никогда не 404. next несёт курсор для следующей страницы или null в конце. alias — второй адрес, который доставляет сюда же и ничего не раскрывает об этом адресе, — отдавайте его форме вместо address; тот, у кого есть только он, всегда видит пустой ящик. Он стабилен, бесплатен и возвращается также для премиум-адресов.
400
Адрес некорректен, либо before не является id сообщения.
400
address отсутствует или не является допустимым адресом.
401
Отправлен ключ API, но он неизвестен или отозван. Неверный ключ отклоняется на любом домене; публичным доменам он вообще не нужен.
402
Только для премиум-пула: квота тарифа исчерпана — quota_reached, либо overage_cap / overage_funds, если включено продолжение сверх квоты. Уже удерживаемые адреса продолжают работать.
403
Только для премиум-пула: этот адрес уже удерживает другой подписчик (address_taken).
404
Этот домен не размещён здесь — проверьте запись MX. Именно так — намеренно — отвечает домен премиум-пула, если его читать без ключа от платного тарифа.
429
Превышен лимит запросов. Повторите попытку после задержки, указанной в Retry-After.
GET/api/v1/message/{id}
Заголовки, текстовую часть, HTML-часть и любые вложения.
Удалено. Вызов идемпотентен: повторное удаление всё равно вернёт 200.
400
mailbox отсутствует или недействителен.
404
Такого сообщения в этом ящике нет.
429
Превышен лимит запросов.
Вложения
У каждого письма есть список вложений с готовыми URL. Загружайте вложение с той же
авторизацией, что и само письмо.
GET /api/v1/attachment/{id}?mailbox={address}
Ответ всегда приходит как application/octet-stream с заголовком
Content-Disposition: attachment, независимо от того, что указал
отправитель. Это сделано намеренно: вернуть чужой text/html как есть
означало бы позволить вложению исполниться как странице на этом источнике.
Настоящий тип указан в JSON письма — там это данные, а не команда.
Ошибки
Любая ошибка возвращается в JSON с одними и теми же двумя полями, поэтому клиент
обрабатывает их в одном месте. Категория — в статусе, error — это
стабильный машиночитаемый код, а message предназначен для людей и
может быть переформулирован в любой момент.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_address",
"message": "address must look like name@domain"
}
Никогда не стройте логику на message. Используемые коды — invalid_address, bad_cursor, unknown_domain, not_found, rate_limited, daily_limit_reached, unauthorized, а на премиум-пуле дополнительно — quota_reached, overage_cap, overage_funds, address_taken и address_limit.
Некоторые ошибки содержат не только эти два поля: hint с подсказкой, что делать, ссылку docs, на 404 и 429 — блок premium_pool с ценой пула и тем, как его открыть, а на 429 из-за бесплатного лимита — ещё и блок upgrade о том, какие ограничения снимает платный тариф. Всё это рассчитано на ассистента, который читает тело ответа от чьего-то имени: он сможет передать этот вариант дальше, а не сдаться.
Лимиты запросов
Бесплатно, без ключа: до 60 запросов в минуту и до 1 000 в сутки с одного IP-адреса. Учитывается каждый вызов к ящику — получение списка, чтение письма, его HTML-версии или вложения, удаление, — а также каждый вызов инструмента MCP. Суточный счётчик обнуляется в 00:00 UTC.
С бесплатным ключом API тот же лимит привязан к вашему аккаунту, а не к IP-адресу — удобно, когда вызовы идут с меняющихся адресов, например с CI-раннера. У бесплатного аккаунта один ключ, а ящики, которые он читает, появляются в ваших ящиках. Создать бесплатный ключ
В этих пределах действует одно чтение в секунду на адрес: опрашивать ящик раз в секунду — предусмотренный ритм.
У платных тарифов нет ни поминутного, ни суточного лимита. Передайте ключ платного тарифа в заголовке Authorization: Bearer — и останется только лимит тарифа на адрес: 2, 3 или 5 запросов в секунду на любом домене, а счёт ведётся по аккаунту. Premium — от $12,99 в месяц. Посмотреть тарифы
Ящик на этом сайте не расходует бесплатный лимит API: оставьте страницу открытой — она будет проверять почту столько, сколько вам нужно.
При превышении лимита вы получите 429 с заголовком Retry-After в целых секундах: rate_limited — при превышении поминутного лимита или лимита на адрес, daily_limit_reached — при исчерпании суточного, и тогда в заголовке указано время до полуночи UTC. В каждом бесплатном ответе видно, сколько осталось: X-RateLimit-Remaining — на текущую минуту, X-RateLimit-Daily-Remaining — на текущие сутки.
Срок хранения
Письмо удаляется через 5 дней
после получения — прочитано оно или нет. У каждого письма есть поле
expires_at, так что вычислять эту дату самостоятельно не нужно.
Это жёсткий предел, а не настройка — никакой параметр его не продлевает. Если
письмо должно пережить это окно, заберите его и сохраните на своей стороне.
Собственный домен
Направьте свою MX-запись на smtp.grabmail.io, и каждый адрес на
вашем домене начнёт отвечать через эти же эндпоинты — учить второй API не нужно,
регистрироваться не нужно, и ключ не нужен.