API de prueba de spam: email,
bandeja de entrada y dominio
Envíanos un mensaje real o indícanos solo un dominio. Todo responde en JSON.
Sin clave, sin cuenta.
Solicitud
# reserve a single-use address
$ curl -sX POST '.../api/v1/inbox?lang=en'
# send your message to that address, then
$ curl -s '.../api/v1/tests/k7m2x9qplw4tz8vn3b6c/status'
# read the report
$ curl -s '.../api/v1/tests/k7m2x9qplw4tz8vn3b6c'
Respuesta
200 OK
{
"address": "test-k7m2x9qplw4tz8vn3b6c@t.email-spam-tester.com",
"slug": "k7m2x9qplw4tz8vn3b6c",
"expires_at": "2026-10-31T13:00:00Z"
}200 OK
{
"analysis_status": "checks_ready",
"ai_status": "running",
"checks_done": 42,
"checks_total": 42
}200 OK
{
"score_ours": 86.4,
"score_compat": 9.2,
"subscores": {"auth": 100.0, "infra_spam": 78.1, "content": 92.0},
"complete": true,
"checks": [{"id": "auth.dmarc", "status": "warn"}],
"fixes": [{"id": "dmarc-enforce", "gain_ours": 4.0}]
}Solicitud
# create a test
$ curl -sX POST '.../api/v1/placement' \
-d '{"public_results_accepted":true}'
# put the marker in the subject, send once to all, then
$ curl -s '.../api/v1/placement/wR3kP9xLq2vT8mZc'
Respuesta
201 Created
{
"marker": "est-3f9a1c7e2b4d6a80c5e1f2d3",
"status": "waiting",
"results": [{"provider": "gmail", "placement": "pending"}],
"fleet": {"status": "observing", "results": [
{"provider": "yahoo", "placement": "pending"},
{"provider": "outlook", "placement": "pending"}
]}
}200 OK
{
"status": "complete",
"results": [{"provider": "gmail", "placement": "primary"}],
"fleet": {"status": "finished", "results": [
{"provider": "yahoo", "placement": "inbox"},
{"provider": "outlook", "placement": "spam"}
]}
}Solicitud
# no email needed, one GET
$ curl -s '.../api/v1/infra/check?domain=example.com'
# compare with your last run
$ curl -s '.../api/v1/infra/check?domain=example.com&diff=true' \
| jq '.diff'
Respuesta
200 OK
{
"domain": "example.com",
"ok": false,
"status": "fail",
"score": 78,
"coverage": {"answered": 7, "total": 8},
"sections": {"ptr": {"status": "fail", "core": true}}
}200 OK
{
"changed": true,
"worsened": true,
"status_from": "pass",
"score_from": 100,
"changes": [{"path": "dkim.key.mail.sha256", "kind": "removed",
"severity": "critical", "effect": "worsened"}]
}Elige el que necesitas
En esta página
Prueba de correo
Leemos un mensaje real de principio a fin: el contenido, la firma, las cabeceras y el servidor que lo ha enviado. Obtienes una puntuación, una lista de correcciones y todas las comprobaciones que las respaldan.
Inicio rápido
Tres llamadas. Sin clave, sin cuenta, sin registro. Dos solicitudes y un correo electrónico. La tercera llamada solo es necesaria porque el análisis tarda unos segundos.
Reserva una dirección
Haz un POST al endpoint de la bandeja de entrada. Recibirás una dirección que acepta exactamente un mensaje y caduca en una hora, además del slug con el que se identifica todo lo demás.
Solicitud
# 1. reserve a single-use address curl -sX POST 'https://email-spam-tester.com/api/v1/inbox?lang=en'Respuesta
{ "address": "test-<slug>@t.email-spam-tester.com", "slug": "<slug>", "expires_at": "2026-01-01T12:00:00Z" }Envíale el mensaje real
Mediante SMTP, desde la plataforma que enviará la campaña. La mitad de las comprobaciones leen las cabeceras que añade tu plataforma de envío, por lo que un mensaje redactado a mano mide algo distinto.
Solicitud
# 2. send your message to that address, from your own platform To: test-<slug>@t.email-spam-tester.comConsulta el estado y después el informe
El endpoint de estado ocupa unos cientos de bytes y te indica si ya merece la pena obtener el informe completo. El informe en sí tiene varios miles de líneas.
Solicitud
# 3. poll curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>/status'Respuesta
{ "slug": "<slug>", "analysis_status": "checks_ready", "ai_status": "running", "checks_done": 42, "checks_total": 42 }Solicitud
# 4. read the report once analysis_status is checks_ready curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>'Respuesta
{ "report_url": "https://email-spam-tester.com/t/<slug>", "score_ours": 86.4, "score_compat": 9.2, "subscores": {"auth": 100.0, "infra_spam": 78.1, "content": 92.0, "compliance": 75.0}, "complete": true, "checks": [ { "id": "auth.dmarc", "status": "warn", "title": "DMARC result", "summary": "DMARC passes, but the policy is p=none.", "weight_ours": -4.0, "evidence": {"policy": "none", "aligned": "dkim"}, "citations": {"standards": [{"title": "RFC 9989 §4.7", "quote": "..."}]} } ], "fixes": [ {"id": "dmarc-enforce", "gain_ours": 4.0, "gain_compat": 0.0, "fix": {"title": "Move DMARC to quarantine", "severity": "medium"}} ] }
Reserva una dirección, envía el mensaje que estabas a punto de enviar a tu lista y consulta el informe. Todo lo que muestra la página está en el JSON, incluida la puntuación, las 42 comprobaciones con sus evidencias y la sección del estándar en la que se basa cada resultado.
Los primeros 100.000 informes son gratuitos, sin clave y sin cuenta. Si estás configurando un agente en lugar de un script, el servidor MCP es más adecuado que el sondeo.
Endpoints
Dirección base https://email-spam-tester.com. Todo responde en JSON.
POST/api/v1/inbox
Reserva una dirección de un solo uso. Ambos parámetros son opcionales.
| lang | Idioma en el que se redactarán el plan de corrección y los resultados de cada comprobación, como código ISO. Se decide ahora porque el mensaje llega por SMTP minutos después y no contiene ninguna indicación de quién lo espera. Un código desconocido utiliza el inglés de forma predeterminada. |
| utm_source, utm_medium, utm_campaign | Se transfieren a nuestras analíticas. Es útil si estás midiendo tu propia integración. |
GET/api/v1/tests/{slug}/status
Su consulta periódica tiene un coste bajo. Devuelve los dos campos de estado y el progreso de las comprobaciones, y nada más.
GET/api/v1/tests/{slug}
El informe completo. Responde con 202 mientras la dirección está reservada y todavía no ha llegado nada, y con 200 una vez que ha llegado.
GET/api/v1/tests/{slug}/message
El mensaje exactamente como se entregó: todas las cabeceras en el orden de transmisión, ambos cuerpos, la lista de archivos adjuntos y el código fuente sin procesar. Se obtiene por separado porque el informe se consulta periódicamente y esto puede llegar a ocupar un megabyte.
PUT/api/v1/tests/{slug}/locale
Cambia el idioma de una reserva que aún no se ha utilizado. Para un agente que averigua qué idioma lee su usuario después de haber solicitado ya la dirección. Se rechaza una vez que el mensaje ha llegado, porque para entonces el análisis está en curso.
Ubicación en la bandeja de entradaBeta
Envía un mensaje a una lista de bandejas de entrada de prueba y consulta dónde ha llegado en Gmail, Outlook, Yahoo y otros proveedores: Bandeja de entrada, Promociones o Spam.
Inicio rápido
Crea una prueba
Haz una solicitud POST al endpoint de colocación. Recibirás un marcador y las bandejas de entrada de prueba.
Solicitud
# 1. create a test curl -sX POST 'https://email-spam-tester.com/api/v1/placement' \ -H 'Content-Type: application/json' \ -d '{"public_results_accepted":true}'Respuesta
{ "slug": "<slug>", "marker": "est-3f9a1c7e2b4d6a80c5e1f2d3", "status": "waiting", "deadline": "2026-10-31T12:30:00Z", "poll_after_seconds": 60, "results": [ {"address": "<seed>", "provider": "gmail", "kind": "Gmail", "placement": "pending", "observed_at": null} ], "fleet": { "status": "observing", "results": [ {"address": "<mailbox>", "provider": "yahoo", "available": true, "placement": "pending", "coverage": "pending"} ] } }Envía un mensaje a cada bandeja de entrada
Pon el marcador en el asunto y envía el mensaje desde tu plataforma habitual a todas las direcciones de una vez.
Solicitud
# 2. one message to every address, with the marker in the subject Subject: October invoice est-3f9a1c7e2b4d6a80c5e1f2d3 To: <seed>, <mailbox>, ...Consulta las carpetas
Cada dirección se completa con su proveedor y carpeta. Consulta hasta que el estado deje de ser waiting.
Solicitud
# 3. poll for the folders curl -s 'https://email-spam-tester.com/api/v1/placement/<slug>'Respuesta
{ "status": "complete", "received": 2, "total": 2, "results": [ {"address": "<seed>", "provider": "gmail", "kind": "Gmail", "placement": "primary", "observed_at": "2026-10-31T12:04:11Z"}, {"address": "<seed>", "provider": "gmail", "kind": "Google Workspace", "placement": "promotions", "observed_at": "2026-10-31T12:04:11Z"} ], "fleet": { "status": "finished", "results": [ {"address": "<mailbox>", "provider": "yahoo", "available": true, "placement": "inbox", "coverage": "ok"}, {"address": "<mailbox>", "provider": "outlook", "available": true, "placement": "spam", "coverage": "ok"} ] } }
Endpoints
An optional test using public GMass seed inboxes and available project test mailboxes, alone or alongside the email score. Explain to the sender that GMass receives their email and publishes its subject, sender name and placement before creating a test. Use all test mailboxes for non-confidential test messages only.
GET /api/v1/placement/availability
Returns providers: the provider identifiers of currently healthy,
admitted project mailboxes. No addresses or credentials are exposed. This read does
not create a test or contact GMass. Actual recipients are allocated at creation and
may differ as availability or capacity changes.
POST /api/v1/placement
Send JSON {"public_results_accepted":true}. Returns HTTP 201 with
slug, marker, results (the seed addresses),
deadline and expires_at. Limit: 20 tests per IP per UTC day.
For one-send combined testing, first reserve an email score address and include
its score_slug in the placement creation JSON. Repeated creation for
that score returns the same placement test. Send the marked email to the score
address, every returned seed and every available fleet.results address;
keep the main /t/<score_slug>
report link. Creating a link after the score address was used or expired returns HTTP 409.
GET /api/v1/placement/by-score/{score_slug}
Read and refresh the placement run attached to the main email test. The response has the same format and polling limits as the standalone endpoint below. HTTP 404 means placement was not included or its stored results have been removed.
GET /api/v1/placement/{slug}
Use poll_after_seconds (normally 60 seconds) while the page is open.
Upstream errors trigger a shared cooldown. Add the marker to the subject and
send through the sender's normal platform to every seed. Observations are saved for
30 days. Collection ends after 30 minutes or when all seeds have results.
status: waiting, complete or timed_out. Each result has an address,
provider, kind, placement and observed_at. Placement is primary, promotions, inbox,
updates, social, forums, spam, unknown, pending or not_observed. Missing results do
not mean Spam; Promotions is an inbox category. provider_error indicates
an upstream outage without discarding saved observations. HTTP 404 means unknown,
410 expired, 429 quota exhausted, and 503 no test inboxes available at creation.
The optional fleet object contains independently collected project
mailbox results, with status observing, settling or finished. Refresh
every 30 seconds until it finishes, even when Gmail has completed. Each fleet result
includes address, provider, available,
placement, category and coverage. Exclude
unavailable addresses from new sends; retain their saved observations. Category
data may be unavailable even when the physical folder is known.
If GMass is unavailable at creation but project mailboxes can be allocated,
provider is fleet and the top-level seed results are empty.
Use fleet.results; do not interpret an empty Gmail list as successful
delivery. Existing runs never gain new recipient addresses silently.
Comprobación de infraestructura
Una solicitud GET comprueba la configuración de correo de un dominio sin enviar nada, conserva el resultado y te indica qué ha cambiado desde la última ejecución. No se necesita ninguna clave. En cron, la línea siguiente termina con un código distinto de cero cuando el dominio está dañado o su configuración ha cambiado de una forma relevante.
Inicio rápido
Haz una solicitud GET
Pasa el dominio. ip añade tus direcciones de envío y selector indica los selectores DKIM que se deben leer.
Solicitud
curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true'Lee el veredicto
ok es la respuesta para un script y sections muestra qué parte ha fallado.
Respuesta
{ "id": "ir_01JB8Y4T2M6K9QZ7H3V5N1XWDA", "domain": "example.com", "checked_at": "2026-10-31T12:00:00Z", "ok": false, "status": "fail", "score": 78, "coverage": {"answered": 7, "total": 8}, "ips": [{"ip": "203.0.113.5", "sources": ["mx", "spf"], "managed": false}], "sections": { "dkim": {"status": "pass", "core": true, "findings": [], "data": {}}, "ptr": {"status": "fail", "core": true, "findings": [], "data": {}} }, "not_checked": [ {"check": "dkim_signature", "reason": "needs_a_message"}, {"check": "alignment", "reason": "needs_a_message"} ], "diff": { "baseline": {"id": "ir_01JB2...", "checked_at": "2026-10-24T12:00:00Z"}, "first_run": false, "changed": true, "worsened": true, "status_from": "pass", "score_from": 100, "changes": [ {"path": "dkim.key.mail.sha256", "section": "dkim", "kind": "removed", "severity": "critical", "effect": "worsened", "from": "9f2c...", "to": null} ], "not_compared": [ {"path": "blocklist_ip.203.0.113.5.bl.spamcop.net.listed", "reason": "lookup_failed"} ] } }Ponlo en cron
Con diff=true, cada ejecución se compara con la última y jq convierte la respuesta en un código de salida.
Solicitud
# exits non-zero if the domain is broken or its setup changed curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true' \ | jq -e '.ok and (.diff.changed | not)'
| domain | Obligatorio. Acepta lo mismo que las herramientas: un dominio, una URL o una dirección de correo electrónico. |
| ip | Tu dirección de envío. Repítela para añadir más, hasta 6. |
| selector | Un selector DKIM. Repítelo para añadir más, hasta 10. Cada selector que pases tiene que existir o dkim falla. |
| helo | El nombre que tu servidor proporciona en HELO, comparado con su PTR. |
| account | Para quién es la solicitud. Obligatorio con una clave que sirve a muchas personas. |
| checks | Secciones que se deben ejecutar, separadas por comas. Todas de forma predeterminada. |
| diff | true compara esta ejecución con tu última ejecución del dominio. |
| since | 7d, 12h o una fecha ISO 8601. Compara con la ejecución más cercana a ese momento en un intervalo de 12 horas; de lo contrario, con la última anterior. Activa diff. |
| baseline | El id de una de tus ejecuciones con la que comparar. Activa diff. |
| fresh | true omite la caché de 60 segundos. |
Lectura de la respuesta
Una comprobación que ha terminado responde con 200, y el veredicto está en el cuerpo. status es el peor estado de las secciones obligatorias: spf, dkim, dmarc, ptr, blocklist_ip, blocklist_domain, mx y smtp. unknown en una sección obligatoria cuenta como warn. ok es true cuando status es pass o warn. score va de 0 a 100 para las secciones obligatorias que respondieron, y es null cuando los errores y los estados unknown dejan menos de la mitad del peso aplicable. mta_sts, tls_rpt, bimi, dnssec, dane, ns y registration se incluyen y se comparan, pero no afectan a ok ni a score.
Una sección puede ser pass, warn, fail, error (no hemos podido comprobarla), unknown (hay muy poca información) o skipped (no se aplica). skipped no afecta al resultado, y el motivo está en not_checked. dkim_signature y alignment siempre están presentes, porque necesitan un mensaje real.
Qué cambian ip y selector
PTR y las listas de bloqueo se refieren a direcciones, por lo que una ejecución necesita algunas. Usa los valores de ip que proporcionas. Si no proporcionas ninguno, toma hasta cuatro de tus hosts MX y de los términos ip4: e ip6: de una sola dirección del registro SPF raíz. Las direcciones de un proveedor de correo conocido se indican como managed y no se comprueban, y si no queda ninguna, ptr y blocklist_ip responden con skipped. Un selector no puede obtenerse de DNS, por lo que una ejecución prueba el tuyo, los que encontraron tus ejecuciones anteriores y una lista de nombres comunes. No encontrar nada no demuestra nada, y dkim responde con unknown. Si envías desde tu propio servidor, proporciona ambos.
Qué ha cambiado
Cada entrada de diff.changes tiene un path, un kind (added, removed, changed), una severity (critical, warning, info) y un effect (worsened, improved, neutral). Solo critical y warning establecen diff.changed, por lo que una clave DKIM rotada de la misma longitud, una nueva dirección MX o un certificado renovado mantienen cron en silencio. diff.worsened sigue el effect de cualquier cambio. En una primera ejecución no hay nada con lo que comparar, y diff.first_run lo indica.
Una referencia siempre es una ejecución tuya, por lo que otra persona que compruebe el dominio entre dos de tus ejecuciones no oculta nada. Todo lo que no hayamos podido leer esta vez pasa a diff.not_compared y conserva su último valor conocido, lo que significa que un cambio realizado durante una interrupción aparece cuando la consulta vuelve a funcionar. Una ejecución con un ip o selector diferente permanece en la misma serie, y tampoco se compara aquello sobre lo que no haya consultado.
Por qué una comprobación programada debe usar una clave
Sin una clave, tu historial pertenece a un hash con clave de tu dirección IP, por lo que termina cuando cambia la dirección, y las personas que están detrás de una misma dirección lo comparten: la ejecución de un compañero cambia tu referencia. Con una clave de API personal en Authorization: Bearer, el historial sigue a la clave. Las ejecuciones con una clave se conservan durante 365 días y solo se pueden abrir con esa clave. Las ejecuciones sin clave se conservan durante 30 días y puede abrirlas cualquiera que tenga su id.
6 solicitudes por minuto y 50 al día por IP, o 30 y 500 por clave. Por encima de ese límite, la respuesta es 429 con Retry-After. Una solicitud idéntica en un intervalo de 60 segundos procede de una caché, se marca como cached: true, no guarda ninguna ejecución y no cuenta. La lectura de ejecuciones almacenadas permite 120 solicitudes por minuto y cliente. 503 con Retry-After significa que hay demasiadas comprobaciones en curso o, al leer ejecuciones almacenadas, que el almacenamiento no está disponible. 401 indica una clave incorrecta. 422 incluye detail.code: invalid_domain, invalid_ip, invalid_selector, invalid_check, invalid_since, unknown_baseline o account_required.
Endpoints
GET/api/v1/infra/check
Ejecuta la comprobación. Los parámetros están en la tabla anterior.
GET/api/v1/infra/runs/{public_id}
Una ejecución almacenada, completa. 404 si no existe o pertenece a otra clave.
GET/api/v1/infra/domains/{domain}/runs
Tus ejecuciones de un dominio, primero las más recientes: id, hora, estado, puntuación y número de cambios. Acepta limit (de 1 a 100, 30 de forma predeterminada) y before, un id de ejecución.
GET/api/v1/infra/diff
La misma comparación entre dos ejecuciones almacenadas, ?from=<id>&to=<id>. Necesitas acceso a ambas.
GET/api/v1/infra/checks
Cada sección con su peso, la versión de puntuación y los límites.
Comprobaciones individuales
Cada llamada responde a una pregunta y no conserva ningún historial. Una herramienta ejecuta por sí sola una parte de la comprobación de infraestructura, excepto la herramienta de cabeceras, que lee un mensaje que ya recibiste.
Inicio rápido
Elige una comprobación
Elige la herramienta de la lista siguiente y proporciona el dominio, la dirección o la IP que solicita.
Solicitud
curl -s 'https://email-spam-tester.com/api/v1/tools/spf?domain=example.com'Consulta el estado y los resultados
Cada herramienta responde con un estado y sus resultados. Los campos posteriores dependen de la herramienta.
Respuesta
{ "tool": "spf", "query": {"domain": "example.com"}, "checked_at": "2026-10-31T12:00:00Z", "duration_ms": 412, "status": "fail", "findings": [ {"code": "spf.too_many_lookups", "level": "fail", "params": {"limit": 10, "count": 12}, "message": "RFC 7208 §4.6.4 allows at most 10 DNS lookups, and this record needs 12, so receivers return permerror."} ], "record": "v=spf1 include:_spf.example.net ~all", "lookups": {"count": 12, "limit": 10, "void": 0} }
Endpoints
GET/api/v1/tools/spf
El registro SPF de un dominio: su sintaxis, cada include y redirect seguido, y las consultas DNS que cuesta todo el árbol con respecto al límite de diez. Pasa ?domain=example.com.
GET/api/v1/tools/dmarc
El registro DMARC de un dominio, o el de su dominio organizativo cuando no tiene ninguno: las etiquetas, la política y si cada dirección externa para informes ha aceptado recibirlos. Pasa ?domain=example.com.
GET/api/v1/tools/dkim
La clave DKIM publicada para un selector: si existe y se decodifica, su tipo y tamaño, y los indicadores de revocación y prueba. Pasa ?domain=example.com&selector=s1.
GET/api/v1/tools/blocklist
Una dirección IPv4, una dirección IPv6 o un dominio comprobado en las listas de bloqueo DNS que utiliza el informe, con la respuesta de cada lista. Pasa ?target=203.0.113.5.
GET/api/v1/tools/mx
Los registros MX de un dominio en el orden en que los remitentes los prueban, con las direcciones IPv4 e IPv6 de cada host. Se informa de un MX nulo, un dominio sin MX, hosts que son direcciones IP o CNAME y hosts que no se resuelven, así como de los registros MTA-STS y TLS-RPT. Pasa ?domain=example.com.
GET/api/v1/tools/bimi
La configuración de BIMI de un dominio en cuatro pasos: la política DMARC que requiere BIMI, el registro en default._bimi, el logotipo SVG comprobado con el perfil Tiny PS y el certificado de marca con su tipo, dominios y fecha de caducidad. Pasa ?domain=example.com y &selector= para un selector distinto de default.
GET/api/v1/tools/ptr
Los registros PTR de una dirección y si alguno de esos nombres vuelve a resolver a ella. Una consulta fallida es error; un registro ausente es fail. Pasa ?ip=8.8.8.8.
GET/api/v1/tools/mta-sts
El registro MTA-STS de un dominio y el archivo de políticas al que apunta: el modo, los hosts enumerados y cualquier host MX que la política omita. Pasa ?domain=example.com.
GET/api/v1/tools/tls-rpt
El registro TLS-RPT de un dominio y las direcciones que reciben sus informes. Pasa ?domain=example.com.
GET/api/v1/tools/dnssec
Si la zona de un dominio está firmada, sin firmar o dañada, según sus registros DNSKEY y DS. Una firma no válida se distingue de una interrupción del servicio del resolutor. Pasa ?domain=example.com.
GET/api/v1/tools/dane
Los registros TLSA de los hosts MX, comparados con el certificado que presenta un host cuando se puede leer dicho certificado. Pasa ?domain=example.com.
GET/api/v1/tools/smtp
STARTTLS y el certificado de los dos primeros hosts MX: versión de TLS, emisor, fecha de caducidad y si la cadena y el nombre son válidos. Solo nos conectamos a hosts bajo el dominio que has consultado y omitimos los proveedores de correo, y cada resultado por dirección se comparte durante 6 horas. No se envía ningún correo. Pasa ?domain=example.com.
GET/api/v1/tools/ns
Los servidores de nombres de un dominio y si su zona tiene un registro SOA. Un solo servidor de nombres genera una advertencia. Pasa ?domain=example.com.
GET/api/v1/tools/registration
Cuándo caduca el registro de un dominio, según RDAP. Si quedan menos de 30 días, se genera una advertencia. Una zona sin servicio RDAP devuelve skipped. Pasa ?domain=example.com.
POST/api/v1/tools/header
Las cabeceras de un mensaje recibido, enviadas como JSON {"headers": "..."} o como text/plain: la ruta salto a salto con los retrasos, TLS y el desfase del reloj, el Authentication-Results propio del receptor, la alineación de los dominios From, DKIM d= y Return-Path, y las cabeceras de DKIM, ARC, cancelación de suscripción y filtros de spam. Todo lo que aparece después de la primera línea vacía se descarta sin leer. Las cabeceras se procesan en memoria y no se almacenan, se guardan en caché ni se registran.
Comprueba el dominio cada noche.
Prueba el correo antes de enviarlo.
Común a todos los productos
Acceso, claves, formato del informe, estados, errores, además de OpenAPI y llms.txt para máquinas.
Autenticación
No hay ninguna. No hay que solicitar ninguna clave, establecer ninguna cabecera ni crear ninguna cuenta. El slug que recibes es la capacidad: quien lo tenga puede leer ese informe y nadie más puede adivinarlo.
Claves de API personales
Everything above works without a key. A key is for automation platforms such as
Zapier, where every user's calls come from the platform's servers and per-IP limits
would be shared by all of them. With a key, limits count per key (50 tests a day,
3 with placement, 5 permanent mailboxes), the key's tests form a history, and the
key can keep permanent mailboxes whose reports only it can read. Send the key as
Authorization: Bearer est_live_… on any call on this page. The routes
below also take account, a short name of your choosing
([A-Za-z0-9_-], up to 64 characters) that keeps separate lists under one
key. GET /api/v1/installations/tests requires it; pass the same one on
POST /api/v1/inbox so the test shows up there. The Zapier integration
uses zapier.
POST /api/v1/keys
Send JSON {"email":"you@example.com"}. Returns HTTP 201 with
key and email. The key is shown once; only its hash is
kept. Asking again gives a new key and leaves the earlier ones working. Limit: 5 keys
per IP per UTC day. The form on /zapier/ calls this.
GET /api/v1/keys/me
Returns email, key_prefix and created_at of
the key in the header, or HTTP 401. Use it to check a key.
GET /api/v1/installations/tests
The key's tests, newest first: ?account=…&limit=50 (up to 100),
and before=<slug> for the next page. Each item has
slug, created_at, analysis_status
(waiting or expired before an email arrived),
score_ours, score_compat, placement and
changes, the checks that moved since the previous test of the same
sending domain. Read the full report at /api/v1/tests/{slug}.
POST /api/v1/installations/mailboxes
Send JSON {"domain":"example.com","account":"…"}. Returns the
permanent mailbox of that sending domain: id, address,
domain, state, daily_cap and
created. HTTP 201 when it is new, 200 when it already existed, 409 when
the key keeps as many mailboxes as it may. Subscribe the address to a newsletter or
a sequence and every email that arrives is checked. GET on the same
path with ?account=… lists them, and DELETE
/api/v1/installations/mailboxes/{mailbox_id} stops one.
GET /api/v1/installations/mailboxes/{mailbox_id}/letters
The emails that arrived, oldest first, paged with after_id and
next_after_id. settled=true ends the page before the first
email still being checked, so paging never skips one. newest=true turns
the order round, for a quick look at the latest; settled does nothing
with it. Each has
test_id, slug, received_at,
analysis_status, score_ours, score_compat,
subject, from_addr and kind.
GET /api/v1/installations/letters/{slug}
The report of one email in a permanent mailbox, the same JSON as
/api/v1/tests/{slug} with report_url null: there is no
public page for it. HTTP 410 once the report has expired.
Lectura del informe
Los campos que contienen la respuesta, en el orden en que probablemente los necesites.
| score_ours | De 0 a 100. Nuestro modelo. La autenticación y la infraestructura tienen la mayor parte del peso, porque deciden la entrega antes de que un filtro lea una palabra del texto. |
| score_compat | De 0 a 10. Reproduce la puntuación de estilo SpamAssassin que ya se suele comparar, para que el informe sea comparable con lo que alguien haya visto en otro lugar. |
| subscores | La misma escala de 0 a 100 por sección: auth, infra_spam, content, compliance. |
| checks[] | Las 42, cada una con un estado, una conclusión de una línea, las pruebas en las que se basó la decisión y lo que restó a las dos puntuaciones. |
| checks[].citations | De dónde procede el hallazgo: la sección del RFC, citada textualmente, y la página donde Google establece su propio requisito. Recopilado manualmente en lugar de generarse, por lo que se puede confiar en ello. |
| fixes[] | Qué cambiar, en orden, con los puntos que vale cada cambio. Las mejoras se calculan volviendo a puntuar el informe, no se estiman. |
| complete | Es falso cuando no se pudo ejecutar una comprobación. Un elemento no comprobado nunca se considera aprobado, así que trata la puntuación como optimista hasta que sea verdadero. |
| report_url | La página legible para personas. Entrégasela a una persona en lugar de un bloque de JSON. |
Estados
Una comprobación puede tener uno de cinco estados, y la diferencia entre dos de ellos importa más de lo que parece.
| pass | La comprobación se ejecutó y no encontró ningún problema. |
| warn | Conviene corregirlo. Resta puntos. |
| fail | Perjudicará la entrega. Cuesta más puntos. |
| omitir | No se aplicó. No hay archivos adjuntos que analizar ni parte HTML que evaluar. No es un resultado aprobado. |
| error | No pudimos determinarlo. Se excluye de la puntuación y se marca, en lugar de contarse como un resultado aprobado. |
analysis_status pasa por received, analyzing, checks_ready, failed. ai_status pasa por pending, running, ready, fallback, error. El informe determinista es definitivo en checks_ready; ai_status solo añade el plan.
Qué puede devolverse
| 202 | La dirección está reservada y no ha llegado ningún mensaje. El cuerpo contiene la dirección, la fecha de expiración y el idioma, por lo que quien realiza la llamada puede mostrarlos aunque no haya creado la reserva. |
| 404 | No existe ese slug. Nunca existió o se olvidó la reserva. |
| 410 | La dirección expiró antes de que llegara un mensaje. |
| 409 | Intentaste cambiar el idioma después de que el mensaje ya hubiera llegado. |
| 429 | El límite de pruebas gratuitas para tu dirección. Actualmente no hay ningún límite por persona en este servicio; si alguna vez se establece uno, el cuerpo indica cuándo se restablece. |
Cuatro cosas que conviene saber
Un mensaje por dirección
El segundo se rechaza. Tu informe anterior permanece intacto, que es precisamente el objetivo.
Una hora para usarla
La dirección caduca; el informe no. Los enlaces a los informes son permanentes, así que uno pegado en un ticket sigue funcionando.
Envía desde la plataforma
Probar una campaña desde una cuenta personal mide esa cuenta. Casi todo lo que aparece en la sección de autenticación se refiere a la infraestructura de envío, no al texto.
Repite la prueba después de corregir
Las mejoras esperadas se calculan para una corrección cada vez y no son acumulativas. El segundo informe muestra la cifra real.
Para máquinas
- /api/openapi.json La descripción OpenAPI, generada a partir del mismo código que sirve la API.
- /llms.txt, /llms-full.txt Un mapa breve de este sitio para modelos de lenguaje, según la convención llms.txt, y una versión más extensa con el ciclo completo y los campos del informe en un solo archivo.
- /mcp Un servidor MCP con la misma capacidad y una espera bloqueante, que supera al sondeo desde dentro de un modelo.
- For agents La página del agente: cuándo recurrir a esto, cómo interpretar una comprobación omitida frente a una superada y qué hallazgos son registros DNS que una persona debe cambiar en lugar de texto que un agente puede editar.
GET/api/health
Comprobación de actividad. Sin autenticación, sin efectos secundarios.
Prueba primero uno manualmente
Tarda aproximadamente un minuto y te muestra exactamente lo que describe el JSON.
Obtener una dirección de pruebaEntorno de pruebas.
Cada endpoint, con un botón que lo ejecuta contra el servicio en producción. Nada de lo que hay aquí necesita una clave, así que cualquier solicitud que envíes desde esta página es real: reserva una dirección real y cuenta.
Pruébalo en el entorno de pruebas