Tres endpoints, JSON de entrada y JSON de salida. Sin clave ni cuenta en dominios
públicos: pega una solicitud en una terminal y funciona.
Resumen
Un buzón nunca se crea: existe en el momento en que llega un mensaje a una
dirección, y desaparece 5 días después. No hay
nada que registrar, así que en dominios públicos la API no tiene concepto de
usuario, proyecto o token.
Toda respuesta es JSON, incluido cada error.
Todas las horas están en UTC en formato RFC 3339: 2026-08-04T18:31:07Z.
Los ids de mensaje son cadenas opacas. No los analices.
Solo recepción. No existe un endpoint para enviar correo, de forma intencional.
URL base
https://grabmail.io/api/v1
Solo HTTPS; el HTTP simple se redirige. La versión está en la ruta, y
v1 no cambiará de forma bajo tus pies: un cambio incompatible obtiene
un número nuevo.
Autenticación: ninguna
Ninguna en dominios públicos. Cualquiera que conozca una dirección puede
leer su buzón, a través de la API igual que a través del sitio web. Ese es
el trato que ofrece un servicio de correo desechable compartido, así que nunca uses una dirección pública
para algo que te importe.
Un dominio que apuntes aquí responde en estos mismos endpoints, tampoco
con clave. Apunta el MX hacia nosotros y el primer mensaje lo conecta; consulta
conectar un dominio. Los buzones de ese dominio los puede leer cualquiera que conozca la
dirección, igual que en los dominios públicos.
La única credencial de esta API es la clave de tu cuenta, descrita más abajo — una con una cuenta gratuita, más con los planes de pago. Una clave no tiene nivel propio: cada llamada se juzga según el plan que tiene su cuenta en ese momento, así que la misma clave pierde los topes gratuitos y abre el grupo premium en cuanto te suscribes, y vuelve a la cuota gratuita cuando el plan termina. Los dominios públicos no necesitan ninguna; enviada con ellos, cuenta tus llamadas para tu cuenta en lugar de para tu dirección IP. Una clave enviada que sea desconocida o esté revocada responde 401 con unauthorized en todos los endpoints, sea cual sea el dominio — así que un error tipográfico se nota al instante en vez de parecer un buzón vacío.
Dominios premium
La única excepción a la regla anterior. Los dominios públicos
están en las listas públicas de correo desechable, por eso un formulario de registro
rechaza a veces una dirección alojada en ellos. Un plan de pago abre un pool de
97 dominios .com privados, fuera de esas listas.
La API no cambia en nada. Mismas rutas, mismos parámetros, mismas formas de respuesta. La única diferencia es una cabecera: una dirección premium se lee con Authorization: Bearer gm_live_…, con una clave de sus claves de API. Sin una clave de un plan de pago, la misma petición responde 404 — palabra por palabra la respuesta de un dominio que no alojamos, a propósito, para que el pool no pueda enumerarse adivinando nombres. Nunca un buzón.
Dónde están los dominios del pool
GET /api/v1/domains con tu clave devuelve los dominios públicos y los nombres de dominio del pool. La misma llamada sin clave — o con una clave de una cuenta gratuita o caducada — devuelve los dominios públicos, cuántos dominios tiene el pool y cuánto cuesta, pero nunca un nombre: mantenerlos fuera de las listas negras de correo desechable es lo que compra el plan. Un suscriptor que ha iniciado sesión también ve el pool en el selector de dominio de la página de inicio.
GET /api/v1/me es la única llamada que evalúa una clave por sí sola: 200 con el plan, el periodo actual, la cuota consumida y restante, las direcciones retenidas y tu límite de solicitudes — o 401unauthorized si la clave es desconocida o está revocada. Llámala primero cuando algo del pool responda 404: esa respuesta oculta un problema de clave a propósito; esta lo muestra.
Cada caso, y su motivo. Los dos primeros parecen sorprendentes hasta que se lee el motivo.
404
unknown_domain — sin clave, o una clave de una cuenta gratuita o caducada. Idéntico, a propósito, a la respuesta de un dominio que no alojamos: distinguir ambos casos permitiría enumerar el pool adivinando nombres. Comprueba la clave con /api/v1/me.
401
unauthorized — la clave enviada es desconocida o está revocada. Se responde así en todos los endpoints, sea cual sea el dominio: dice algo sobre la clave, nunca sobre un dominio.
402
quota_reached — la cuota de este periodo está agotada y el excedente está desactivado. overage_cap / overage_funds — el excedente está activado, pero se alcanzó el límite que fijaste o el saldo es insuficiente. Las direcciones ya retenidas siguen funcionando en los tres casos.
403
address_taken — otro suscriptor retiene esa dirección. Elige otro nombre.
409
address_limit — reservado para un plan que limita las direcciones. Ningún plan lo hace hoy.
429
rate_limited — en el plan gratuito (sin clave, o con una gratuita), más de 60 solicitudes por minuto, o más de una lectura por segundo en una misma dirección; con una clave de pago, más de 2, 3 o 5 lecturas por segundo en una misma dirección, según el plan. daily_limit_reached — se agotaron las 1.000 solicitudes gratuitas del día. Los planes de pago no tienen ni el tope por minuto ni el diario. Ambos incluyen Retry-After.
Direcciones retenidas y cuota
Una dirección premium queda retenida por la primera cuenta que la lee con una clave válida — cualquier lectura, en cualquier endpoint o a través de MCP, sin nada que reservar de antemano. Mientras está retenida, solo esa cuenta puede leerla; cualquier otra obtiene 403. Sigue retenida hasta que la liberes desde el panel, o hasta que el plan termine — en su fecha de fin, sin periodo de gracia.
La cuota cuenta unidades: un mensaje recibido en una dirección premium o una dirección premium nueva abierta, lo que ocurra primero — así que una dirección que abres y nunca lees también usa una. Volver a leer una dirección retenida es gratis. Ningún plan limita cuántas direcciones retiene una cuenta; la cuota es lo que lo acota, y /api/v1/me muestra lo que queda.
El alias, también en las direcciones premium
Cada buzón listado incluye un alias: una segunda dirección que entrega en el mismo buzón y no revela nada sobre él. Da el alias a un formulario y consulta la dirección; quien conozca el alias siempre verá un buzón vacío. Es estable para una dirección dada, gratis, y se devuelve para las direcciones premium exactamente igual que para las públicas. Su dominio es uno de los nuestros y no aparece listado en ningún sitio, a propósito.
Todo, en cuatro llamadas
KEY="gm_live_…" # desde tu página de claves de API, con un plan de pago
# 1. Comprueba la clave: plan, cuota restante, límite de solicitudes. 401 si es incorrecta.
curl -s https://grabmail.io/api/v1/me -H "Authorization: Bearer $KEY"
# 2. Lista el pool. Los nombres solo aparecen en la respuesta con una clave de pago.
curl -s https://grabmail.io/api/v1/domains -H "Authorization: Bearer $KEY"
# 3. Lee un buzón de una de ellas. Esta primera lectura retiene la dirección y cuenta como una unidad.
curl -sG https://grabmail.io/api/v1/mailbox -H "Authorization: Bearer $KEY" \
--data-urlencode "address=a7f3k2@one-of-the-pool.com"
# 4. Lee un mensaje, misma cabecera.
curl -sG https://grabmail.io/api/v1/message/MESSAGE_ID -H "Authorization: Bearer $KEY" \
--data-urlencode "mailbox=a7f3k2@one-of-the-pool.com"
Los dominios públicos y tus propios dominios siguen siendo gratuitos, sin clave y sin límite en todos los planes, incluido el gratuito. La cuota solo cuenta el pool premium, nada más. Los planes y los precios están en la página de planes.
Endpoints
GET/api/v1/mailbox
Todo lo que espera en una dirección, lo más reciente primero. Esta es la llamada que consulta tu batería de pruebas.
Parámetros
Nombre
Entrada
Tipo
Obligatorio
Descripción
address
query
string
sí
El buzón a leer, p. ej. k7fq2m@grabmail.io.
limit
query
integer
no
Cuántos mensajes devolver en esta llamada, 1–200. Por defecto 50, los más recientes primero. Limita una respuesta, no el buzón — usa before para leer más allá.
before
query
string
no
El id del mensaje más antiguo que ya tienes; devuelve la página siguiente. Reenvía el campo next de la respuesta anterior. Cuando next es null, ya tienes todo.
El buzón se leyó. Un buzón vacío es un 200 con count: 0, nunca un 404. next lleva el cursor de la página siguiente, o null al final. alias es una segunda dirección que entrega aquí y no revela nada sobre esta — dásela a un formulario en lugar de address; quien la conozca siempre verá un buzón vacío. Es estable, gratis, y también se devuelve para las direcciones premium.
400
La dirección no tiene un formato válido, o before no es un id de mensaje.
400
address falta o no es válida.
401
Se envió una clave de API y es desconocida o está revocada. Una clave incorrecta se rechaza en todos los dominios; los dominios públicos no necesitan ninguna.
402
Solo en el pool premium: la cuota del plan está agotada — quota_reached, o overage_cap / overage_funds cuando el excedente está activado. Las direcciones ya retenidas siguen funcionando.
403
Solo en el pool premium: otro suscriptor retiene esa dirección (address_taken).
404
Ese dominio no está alojado aquí — comprueba el registro MX. Un dominio del pool premium leído sin una clave de un plan de pago responde exactamente esto, a propósito.
429
Límite de solicitudes superado. Reintenta después del retraso indicado en Retry-After.
GET/api/v1/message/{id}
Cabeceras, la parte en texto plano, la parte en HTML y los adjuntos.
Parámetros
Nombre
Entrada
Tipo
Obligatorio
Descripción
id
path
string
sí
El id del mensaje devuelto por la llamada de listado.
Eliminado. La llamada es idempotente: eliminar dos veces sigue respondiendo 200.
400
mailbox falta o no es válido.
404
No existe ese mensaje en ese buzón.
429
Límite de solicitudes superado.
Archivos adjuntos
Cada mensaje lista sus adjuntos con una URL ya lista. Descárgalo con
la misma autorización que el mensaje.
GET /api/v1/attachment/{id}?mailbox={address}
Siempre responde application/octet-stream con
Content-Disposition: attachment, sea cual sea la etiqueta que puso el remitente.
Es intencionado: devolver el text/html de un desconocido
permitiría que un adjunto se ejecutara como página en este origen. El tipo real está en
el JSON del mensaje, donde es un dato y no una instrucción.
Errores
Todo fallo es JSON con los mismos dos campos, así que un cliente los gestiona
en un solo lugar. El estado indica la categoría, error es un
identificador estable legible por máquina, y message es para humanos y
puede reformularse en cualquier momento.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_address",
"message": "address must look like name@domain"
}
Nunca decidas según message. Los identificadores en uso son invalid_address, bad_cursor, unknown_domain, not_found, rate_limited, daily_limit_reached, unauthorized y, solo en el pool premium, quota_reached, overage_cap, overage_funds, address_taken y address_limit.
Algunos errores llevan más que esos dos campos: una hint con lo que hay que hacer, un enlace docs, en 404 y 429 un bloque premium_pool con el precio del pool y cómo abrirlo, y en un 429 por límite gratuito un bloque upgrade que explica lo que elimina un plan de pago — pensado para un asistente que lee el cuerpo en nombre de alguien, para que pueda transmitir la opción en vez de rendirse.
Límites de solicitudes
Gratis, sin clave: 60 solicitudes por minuto y 1.000 al día, por dirección IP. Cada llamada sobre un buzón cuenta — listarlo, leer un mensaje, su cuerpo HTML o un adjunto, borrar uno — y también cada llamada a una herramienta MCP. El contador diario se reinicia a las 00:00 UTC.
Con una clave de API gratuita, la misma cuota sigue a tu cuenta en lugar de a tu dirección IP — útil cuando tus llamadas salen de direcciones que cambian, como un runner de CI. Una cuenta gratuita tiene una clave, y los buzones que lee se listan en tus buzones. Crear una clave gratuita
Dentro de ese margen, una lectura por segundo por dirección: consultar un buzón una vez por segundo es el ritmo previsto.
Los planes de pago no tienen tope por minuto ni tope diario. Envía la clave de un plan de pago como Authorization: Bearer y solo queda el límite por dirección de tu plan — 2, 3 o 5 solicitudes por segundo, en todos los dominios, contadas por cuenta. El plan Premium empieza en $12,99 al mes. Ver los planes
La bandeja de entrada de este sitio no consume la cuota gratuita de la API: una página que dejas abierta sigue comprobando si llega correo todo el tiempo que la necesites.
Por encima de un límite recibes 429 con una cabecera Retry-After en segundos enteros: rate_limited para el límite por minuto o por dirección, daily_limit_reached para el límite diario, con el tiempo que queda hasta la medianoche UTC. En el acceso gratuito, cada respuesta te indica cuánto te queda: X-RateLimit-Remaining para el minuto, X-RateLimit-Daily-Remaining para el día.
Retención
Un mensaje se elimina 5 días
después de llegar, leído o no. Cada mensaje incluye
expires_at, así que nunca tienes que calcular esa fecha tú mismo.
Es un límite fijo, no una opción configurable: ningún parámetro lo amplía. Si un mensaje
debe durar más que esa ventana, descárgalo y guárdalo por tu cuenta.
Tu propio dominio
Apunta tu MX a smtp.grabmail.io y todas las direcciones de
tu dominio responderán a través de estos mismos endpoints: sin una segunda API que
aprender, sin registro y sin clave.