Notix
Learn

Check a message before it goes out, not after it bounces.

An email deliverability API takes a message you are about to send and returns what a receiving server is likely to hold against it: an unverified sending domain, marketing mail with no unsubscribe link, spam-filter symbols, suspicious links, an oversized body. It reports on the message and its domain, not on the recipient. Notix exposes its own check as POST /v1/deliverability/check, returning a verdict, a score from 0 to 100 and a list of findings, each with a fix.

Deliverability before a send, and after.

Deliverability is usually discussed after the fact: the bounce rate, the complaint rate, the share of mail that landed in spam. Those are measurements of what receiving servers decided, and by the time you have them the campaign has gone. The decision they made rests on three things. Reputation is the history of your sending domain and IPs, which a new sender has not earned yet and cannot inspect. Authentication is whether SPF, DKIM and DMARC say the mail is really yours. Content is the message itself: its links, images, wording and structure, which is what spam filters score.

Only the last two are visible before a send, and only content is fully within the message you are about to hand over. A pre-send check works on that layer: it renders the message the way a recipient would receive it, runs a spam filter over it, follows its links, and inspects the sending domain’s records. It turns the after-the-fact question “why did that land in spam?” into a before-the-fact one you can act on.

What a pre-send check can tell you, and what it cannot.

It can tell you that the domain in your from address is not verified for sending, which most receivers reject outright. It can tell you that a marketing message has no unsubscribe link, which providers and several jurisdictions require. It can tell you that a spam filter fires on your message and which rules fired, that a link points at a raw IP address or a URL shortener, that an image has no alt text, that the subject is shouting, that a template variable was left unrendered, that the HTML is over 100 KB, or that the domain has no DMARC record.

It cannot tell you what a particular mailbox provider will do. Gmail, Outlook and the rest weigh your reputation with them, the recipient’s past behaviour and signals they do not publish. A message can pass every visible check and still be filtered because the domain sent to a stale list last month. The honest framing is that a check removes the avoidable causes of rejection; it does not promise the inbox.

What the Notix check returns.

The request carries the from address and subject, and either the html body (with an optional text part) or a saved templateId with the variables to render it. A marketing flag says whether the unsubscribe rule applies. The response is one report:

  • verdict: PASS, WARN or BLOCK. It is BLOCK when any block finding is present, WARN when any warn finding is present, else PASS.
  • score: 0 to 100, higher is better. It starts at 100 and loses 5 points per spam-filter point, 15 per warning and 40 per block finding, floored at zero.
  • findings: each with a stable id, a severity of block, warn or info, a title, the detail, and a fix written to be acted on. Ordered block first, then warn, then info.
  • spam: whether the filter answered, its score (higher is worse) and the rules that fired with their descriptions.
  • checkedAt and budgetExceeded: when the report was built, and the ids of any checks that did not finish inside the 15-second budget.

Four findings block. domain_unverified: the from domain is not one of your verified sending domains. unsubscribe_missing: marketing content with no unsubscribe link. link_ip_host: an anchor whose host is a raw IPv4 or IPv6 address. spam_high: the filter scored the message at 10 or more. The warnings cover a medium spam score (4 to 10, with the fired rules named), unreachable or plain-http links, link text that does not match its target, URL shorteners, images without alt text or with almost no visible text beside them, HTML over 102,400 bytes, subjects that are too long, mostly upper case or end in a run of punctuation, unrendered template variables, and a sending domain without a DMARC record. Two infos observe a missing preview text and a missing plain text part.

The call

One request, one report.

Send exactly one of html or templateId. The endpoint answers 200 whenever the message could be rendered; the verdict inside tells you whether a send would be refused.

POST /api/v1/deliverability/check
curl https://app.usenotix.dev/api/v1/deliverability/check \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "news@acme.com",
    "subject": "Your September update",
    "html": "<p>Read the update. <a href=\"https://acme.com/update\">Open it</a></p>",
    "marketing": true
  }'
A WARN report, trimmed
{
  "verdict": "WARN",
  "score": 85,
  "findings": [
    {
      "id": "image_alt_missing",
      "severity": "warn",
      "title": "An image has no alt text",
      "detail": "Filters and screen readers see an image with nothing to describe it.",
      "fix": "Give every image a short alt attribute."
    },
    {
      "id": "text_part_missing",
      "severity": "info",
      "title": "There is no plain text alternative",
      "detail": "Some clients and filters prefer a text part beside the HTML.",
      "fix": "Send a text version alongside the HTML."
    }
  ],
  "spam": {
    "available": true,
    "score": 2.4,
    "symbols": [
      { "name": "HTML_SHORT_LINK_IMG_1", "score": 2, "description": "The email is mostly an image with a link" }
    ]
  },
  "checkedAt": "2026-09-07T12:00:00.000Z",
  "budgetExceeded": []
}

Where to put it in your pipeline.

The check is an API request, not a send, so it costs none of your email allowance; it only counts against the team’s ordinary API rate limit. That shapes where it belongs. Run it when a template is saved, so a broken link or a missing alt is caught by the person who can fix it. Run it in CI against your rendered templates with representative variables, so an unrendered {{ name }} fails the build rather than the customer. Run it before every campaign, which Notix already does for you. Do not wire it in front of every individual transactional send: those messages come from templates you have already checked, and the extra round trip buys nothing.

Treat the three severities differently. A block is a bug: fail the pipeline. A warning is a review item: surface it to whoever owns the template and move on. An info is a suggestion you can batch up.

How Notix handles it.

The same report drives the product. When a team sends a campaign, Notix runs the check first and refuses on BLOCK with the findings shown in place of the confirmation; a WARN shows the warnings once with a “Send anyway”. Activating a journey checks every email step the same way. The template editor shows the panel too, so problems are visible while the message is being written. The spam scoring runs inside the Notix stack rather than through a third-party service, and if that filter is unreachable the report says so and nothing is blocked by the outage. For the transactional email API the check is advisory: you call it on your templates, and the email API sends what you ask it to. Every verified domain, the shared suppression list and the delivery webhooks sit around both paths.

FAQ

Questions, answered.

What is an email deliverability API?
An API you call with a message before you send it, which returns what a receiving mail server is likely to object to: an unverified sending domain, a missing unsubscribe link in marketing mail, spam-filter symbols, broken or suspicious links, an oversized body. It reports on the message and its sending domain, not on the recipient, and it runs before a send rather than after a bounce.
Does a pre-send check guarantee delivery to the inbox?
No, and any tool that says so is overclaiming. The final decision is made by the recipient's mailbox provider using signals nobody outside it can see, including your sending reputation with that provider and the recipient's own behaviour. A check removes the problems that are visible in the message itself, which is where most avoidable rejections start.
Does calling the check cost anything?
The check is an API request, not a send, so it does not consume any of your plan's email allowance; it does count against the team's API rate limit like any other call, and a 429 is the answer when that limit is exceeded. That makes it cheap to run on every template save or before every campaign; it is not built to be called on every individual transactional send.
What happens when the spam filter is down?
The report says so: spam.available is false, there is no spam finding, and every other check still runs. A filter outage never blocks a send. The same applies to the time budget: a check that does not finish inside 15 seconds is listed in budgetExceeded and neither blocks nor warns, so a slow link target cannot hold your campaign hostage.
Which findings actually stop a send?
Four, all with severity block: an unverified from domain, marketing content with no unsubscribe link, a link whose host is a raw IP address, and a spam score of 10 or more. When any of them is present the verdict is BLOCK and the campaign send and journey activation paths refuse. Everything else is a warn or an info: it lowers the score and asks for a fix, but the message can still go.

Read the docs before you decide.

The endpoint, the request fields and every finding id are in the API reference.