Free Email Spam Tester Infra checks API

The Infra checks API from Free Email Spam Tester — 5 operation(s) for infra checks.

GitHub OpenAPI

Operations 5

GET /api/v1/infra/check Check a domain's mail infrastructure #
GET /api/v1/infra/runs/{public_id} One stored run #
GET /api/v1/infra/domains/{domain}/runs Your runs of a domain, newest first #
GET /api/v1/infra/diff What changed between two runs #
GET /api/v1/infra/checks The sections, their weights and the limits #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/email-spam-tester-com:email-spam-tester-com-infra-checks-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

email-spam-tester-com-infra-checks-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Email Spam Tester Infra checks API
  description: 'Test an email before you send it to anybody.


    The loop is three calls. Ask for an address, send the message you were about to

    send your list to that address, then read the report. No key, no account, no

    limit per person on the first 100,000 reports.


    curl -X POST https://email-spam-tester.com/api/v1/inbox

    # send your message to the address it returns, then:

    curl https://email-spam-tester.com/api/v1/tests/


    The address accepts exactly one message and expires after an hour. The report

    link is permanent and carries `report_url` inside the JSON, so a forwarded

    report still says where it came from.


    **Poll `/status`, not `/`.** The full report is several thousand lines of JSON

    and the analysis takes a few seconds; the status endpoint is the cheap way to

    find out whether it is worth fetching yet. `analysis_status` reaches

    `checks_ready` first and the AI plan lands a minute or so later under

    `ai_status`, so a caller that only wants the checks does not have to wait for

    the plan.


    **Agents:** there is an MCP server at `/mcp` with the same capability and a

    blocking wait, which is a better fit than polling from a model.


    Every finding carries `citations`: the section of the RFC it comes from, quoted,

    and the page where Google states its own requirement. Those are curated by hand

    rather than generated, so they can be relied on.'
  contact:
    name: Email Spam Tester
    url: https://email-spam-tester.com/
  version: 1.0.0
tags:
- name: Infra checks
paths:
  /api/v1/infra/check:
    get:
      tags:
      - Infra checks
      summary: Check a domain's mail infrastructure
      description: SPF, DKIM, DMARC, PTR, blocklists, MX and STARTTLS, with MTA-STS, TLS-RPT, BIMI, DNSSEC, DANE, name servers and the registration as advice, all without a message. With `diff=true` the answer says what changed since your last run. A completed check is 200; `ok`, `status` and `not_checked` carry the verdict.
      operationId: check_api_v1_infra_check_get
      parameters:
      - name: domain
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Domain
      - name: ip
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
          description: Sending address, up to 6.
          default: []
          title: Ip
        description: Sending address, up to 6.
      - name: selector
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
          description: Selector, up to 10.
          default: []
          title: Selector
        description: Selector, up to 10.
      - name: helo
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 255
          - type: 'null'
          title: Helo
      - name: account
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
          - type: 'null'
          title: Account
      - name: checks
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Sections, comma separated.
          title: Checks
        description: Sections, comma separated.
      - name: diff
        in: query
        required: false
        schema:
          type: boolean
          default: false
          title: Diff
      - name: baseline
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
          - type: 'null'
          title: Baseline
      - name: since
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: 7d or an ISO 8601 date.
          title: Since
        description: 7d or an ISO 8601 date.
      - name: fresh
        in: query
        required: false
        schema:
          type: boolean
          default: false
          title: Fresh
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InfraOut'
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Unprocessable Entity
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Too Many Requests
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Service Unavailable
  /api/v1/infra/runs/{public_id}:
    get:
      tags:
      - Infra checks
      summary: One stored run
      description: A run made with a key opens only with that key; otherwise 404.
      operationId: read_run_api_v1_infra_runs__public_id__get
      parameters:
      - name: public_id
        in: path
        required: true
        schema:
          type: string
          title: Public Id
      - name: account
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
          - type: 'null'
          title: Account
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InfraOut'
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Not Found
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Too Many Requests
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Service Unavailable
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/infra/domains/{domain}/runs:
    get:
      tags:
      - Infra checks
      summary: Your runs of a domain, newest first
      description: 'Runs of the caller only: a key, or the hash of the address.'
      operationId: list_runs_api_v1_infra_domains__domain__runs_get
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
          title: Domain
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          maximum: 100
          minimum: 1
          default: 30
          title: Limit
      - name: before
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Before
      - name: account
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
          - type: 'null'
          title: Account
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunsOut'
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Unprocessable Entity
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Too Many Requests
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Service Unavailable
  /api/v1/infra/diff:
    get:
      tags:
      - Infra checks
      summary: What changed between two runs
      description: Needs access to both runs; otherwise 404.
      operationId: diff_runs_api_v1_infra_diff_get
      parameters:
      - name: from
        in: query
        required: true
        schema:
          type: string
          title: From
      - name: to
        in: query
        required: true
        schema:
          type: string
          title: To
      - name: account
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
          - type: 'null'
          title: Account
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InfraDiff'
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Not Found
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Too Many Requests
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorOut'
          description: Service Unavailable
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/infra/checks:
    get:
      tags:
      - Infra checks
      summary: The sections, their weights and the limits
      description: 'Static: what /infra/check runs and what it may be asked for.'
      operationId: catalogue_api_v1_infra_checks_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChecksOut'
components:
  schemas:
    InfraIp:
      properties:
        ip:
          type: string
          title: Ip
        sources:
          items:
            type: string
          type: array
          title: Sources
        managed:
          type: boolean
          title: Managed
          description: Run by a provider, so not checked.
      type: object
      required:
      - ip
      - sources
      - managed
      title: InfraIp
    NotCompared:
      properties:
        path:
          type: string
          title: Path
        reason:
          type: string
          enum:
          - lookup_failed
          - not_requested
          title: Reason
      type: object
      required:
      - path
      - reason
      title: NotCompared
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
    DiffBaseline:
      properties:
        id:
          type: string
          title: Id
        checked_at:
          type: string
          title: Checked At
      type: object
      required:
      - id
      - checked_at
      title: DiffBaseline
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    InfraOut:
      properties:
        id:
          anyOf:
          - type: string
          - type: 'null'
          title: Id
          description: Null when the run was not stored.
        domain:
          type: string
          title: Domain
        checked_at:
          type: string
          title: Checked At
        duration_ms:
          type: integer
          title: Duration Ms
        schema_version:
          type: integer
          title: Schema Version
        score_version:
          type: integer
          title: Score Version
        cached:
          type: boolean
          title: Cached
        stored:
          type: boolean
          title: Stored
        ok:
          type: boolean
          title: Ok
        status:
          type: string
          title: Status
        score:
          anyOf:
          - type: integer
          - type: 'null'
          title: Score
        coverage:
          additionalProperties:
            type: integer
          type: object
          title: Coverage
        summary:
          additionalProperties:
            type: integer
          type: object
          title: Summary
        ips:
          items:
            $ref: '#/components/schemas/InfraIp'
          type: array
          title: Ips
        sections:
          additionalProperties:
            $ref: '#/components/schemas/InfraSection'
          type: object
          title: Sections
        not_checked:
          items:
            $ref: '#/components/schemas/NotChecked'
          type: array
          title: Not Checked
        diff:
          anyOf:
          - $ref: '#/components/schemas/InfraDiff'
          - type: 'null'
          description: Null unless diff, since or baseline asked for it.
      type: object
      required:
      - id
      - domain
      - checked_at
      - duration_ms
      - schema_version
      - score_version
      - cached
      - stored
      - ok
      - status
      - score
      - coverage
      - summary
      - ips
      - sections
      - not_checked
      - diff
      title: InfraOut
    ChecksOut:
      properties:
        sections:
          items:
            $ref: '#/components/schemas/CheckRow'
          type: array
          title: Sections
        score_version:
          type: integer
          title: Score Version
        schema_version:
          type: integer
          title: Schema Version
        limits:
          additionalProperties:
            additionalProperties:
              type: integer
            type: object
          type: object
          title: Limits
      type: object
      required:
      - sections
      - score_version
      - schema_version
      - limits
      title: ChecksOut
    NotChecked:
      properties:
        check:
          type: string
          title: Check
        reason:
          type: string
          title: Reason
      type: object
      required:
      - check
      - reason
      title: NotChecked
    ToolErrorOut:
      properties:
        detail:
          $ref: '#/components/schemas/ToolError'
      type: object
      required:
      - detail
      title: ToolErrorOut
    InfraDiff:
      properties:
        baseline:
          anyOf:
          - $ref: '#/components/schemas/DiffBaseline'
          - type: 'null'
        first_run:
          type: boolean
          title: First Run
        changed:
          type: boolean
          title: Changed
          description: A change of severity critical or warning.
        worsened:
          type: boolean
          title: Worsened
        status_from:
          anyOf:
          - type: string
          - type: 'null'
          title: Status From
        score_from:
          anyOf:
          - type: integer
          - type: 'null'
          title: Score From
        changes:
          items:
            $ref: '#/components/schemas/DiffChange'
          type: array
          title: Changes
        not_compared:
          items:
            $ref: '#/components/schemas/NotCompared'
          type: array
          title: Not Compared
        reason:
          anyOf:
          - type: string
          - type: 'null'
          title: Reason
          description: storage_unavailable when nothing could be read or kept.
      type: object
      required:
      - baseline
      - first_run
      - changed
      - worsened
      - status_from
      - score_from
      - changes
      - not_compared
      title: InfraDiff
    CheckRow:
      properties:
        name:
          type: string
          title: Name
        weight:
          type: integer
          title: Weight
          description: Share of the score; 0 means advisory.
        core:
          type: boolean
          title: Core
      type: object
      required:
      - name
      - weight
      - core
      title: CheckRow
    InfraSection:
      properties:
        status:
          type: string
          title: Status
          description: pass, warn, fail, error, unknown or skipped.
        core:
          type: boolean
          title: Core
          description: Counts toward status, ok and score.
        findings:
          items:
            $ref: '#/components/schemas/Finding'
          type: array
          title: Findings
        data:
          additionalProperties: true
          type: object
          title: Data
      type: object
      required:
      - status
      - core
      - findings
      - data
      title: InfraSection
    RunsOut:
      properties:
        runs:
          items:
            $ref: '#/components/schemas/RunRow'
          type: array
          title: Runs
      type: object
      required:
      - runs
      title: RunsOut
    DiffChange:
      properties:
        path:
          type: string
          title: Path
          description: dkim.key.mail.sha256, dmarc.policy, mx.hosts and so on.
        section:
          type: string
          title: Section
        kind:
          type: string
          enum:
          - added
          - removed
          - changed
          title: Kind
        severity:
          type: string
          enum:
          - critical
          - warning
          - info
          title: Severity
        effect:
          type: string
          enum:
          - worsened
          - improved
          - neutral
          title: Effect
        from:
          title: From
        to:
          title: To
      type: object
      required:
      - path
      - section
      - kind
      - severity
      - effect
      - from
      - to
      title: DiffChange
    RunRow:
      properties:
        id:
          type: string
          title: Id
        checked_at:
          type: string
          title: Checked At
        status:
          type: string
          title: Status
        score:
          anyOf:
          - type: integer
          - type: 'null'
          title: Score
        changes_count:
          anyOf:
          - type: integer
          - type: 'null'
          title: Changes Count
      type: object
      required:
      - id
      - checked_at
      - status
      - score
      - changes_count
      title: RunRow
    Finding:
      properties:
        code:
          type: string
          title: Code
          description: Stable identifier, e.g. spf.too_many_lookups. The English template for every code is in /i18n/tools/findings.en.json on the website.
        level:
          type: string
          enum:
          - pass
          - info
          - warn
          - fail
          - error
          title: Level
        params:
          additionalProperties: true
          type: object
          title: Params
          description: Values the message is built from.
        message:
          type: string
          title: Message
          description: The English sentence, params filled in.
      type: object
      required:
      - code
      - level
      - params
      - message
      title: Finding
    ToolError:
      properties:
        code:
          type: string
          enum:
          - invalid_domain
          - invalid_selector
          - invalid_target
          - invalid_ip
          - invalid_check
          - invalid_since
          - unknown_baseline
          - account_required
          - invalid_headers
          - rate_limited
          - busy
          - storage_unavailable
          title: Code
        message:
          type: string
          title: Message
      type: object
      required:
      - code
      - message
      title: ToolError