Help
Search or browse by topic. Can’t find it? Email support.
Getting started
SendLint is an automated email QA platform that checks your HTML emails against 100+ rules covering accessibility, brand compliance, copy accuracy, link validation, spam risk, and rendering compatibility. Upload your email HTML, attach a copy deck, and get a detailed report in seconds.
Visit /demo to paste any HTML and see the analyzer run end-to-end without an account. We'll email you the results. When you're ready to save reports, configure per-client rules, and run AI passes, create an account.
Click "Get started" on the landing page to create an account with your email address. After signing up, you'll be directed to choose a subscription plan. Once subscribed, you'll land on New analysis, where you can start analyzing emails right away.
The top bar has the main sections, left to right: New analysis (where you land — start an analysis), Campaigns (every campaign and where it is), Clients (brand rules and checks), Certificates (every signed-off round) and Tools. On the right: the Inbox icon (a dot means something unread), ? for Help, and your avatar — Profile is you (your details, sign-in, security, feedback) and Settings is the workspace (team, plan and billing, API keys, usage). Hover any icon for its name.
From New analysis:
- Type a Campaign ID (top left — it's required, and it groups the report with the campaign's other emails)
- Pick the client and the language (EN / FR)
- Drop the email into Email HTML — an .html or .eml file, the pasted source, or a preview URL
- Optionally attach the Copy deck and the Creative on the right
- Click Run analysis
Your report opens with pass / fail / warning results grouped by category. Required fields carry a red asterisk; the line beside the Run button says what's still missing.
Each report shows its checks as a donut: red Failed, amber Warnings, green Passed, with the total in the middle (there's no score: send-ready means zero fails). Beside it, from the second round on, are the rounds and what moved since the last one.
Under Checks, the list opens on Issues: the fails and the warnings together. Failed, Warnings and Passed each show one kind, and All shows every check that ran. Checks that didn't run (nothing in the email for them, or not set up for the client) aren't listed; the exported PDF names them under Not run. Pick All and the next report opens on All too.
Results are grouped in sections: Visual Rendering first (the creative comparison with its Design checks, then the Code checks), then Copy, Images, Links, Brand, Accessibility, Metadata and Deliverability. Each section's header says its fails, warnings and passes in words. Each check shows:
- Pass (green): the check passed
- Fail (red): an issue was found that needs fixing
- Warning (amber): a potential issue worth reviewing
Click any result to see details and recommendations.
What's new
The main sections now read left to right — New analysis · Campaigns · Clients · Certificates · Tools — with Inbox, Help and your account as icons on the right. Campaigns is a page of its own: every campaign with its client, where each language is, whether it's signed off and what moved last, filtered by client and Active / Completed. The workspace's team, billing and API keys moved from Profile to Settings (the avatar menu, top right), next to a new Usage tab with this month's AI use. The campaign list that opened from the old Projects button now opens from the Campaigns handle on the left edge of New analysis.
A new Tools section in the top bar: Prepare a deck (any deck plus its links spreadsheet, combined into one), Deck compare (every line that changed between two deck versions, saved as a PDF), Alt text writer (the AI Agent writes alt text for any image), Link sheet (every link followed to where it lands), Subject & pre-header preview (where each inbox cuts them), Image check (size, sharpness, format and alt for every image), Image optimizer (every image resized to the width the email shows it at, as a JPEG or PNG under the 200 KB guideline, in your browser) and Screen reader transcript (every line a screen reader announces, with the hidden pre-header, unnamed links and leaking tables flagged).
Each has Try an example, and the tools hand work to each other: see the Tools section below.
Every analysis mode shares one bar at the top: Campaign ID (required), the round, the client and the language. The round is worked out for you — R1 for a new campaign, the next round for a known one — and Change edits it on the same line. The email (or batch) is marked required, and the Copy deck and Creative cards sit beside them at the same size in every mode.
Drop or paste a .eml (or Outlook web's *View message source*) and SendLint unwraps it and reads the subject line from the message header. Plain HTML has no subject, so a Subject line field appears under it — type the subject as sent; left empty, the page title stands in.
Personalization tokens no longer need typing: SendLint reads what each token should say from the deck and the email (a deck's <Firstname> against the email's rendered name, or a merge tag against the deck's filled-in text) and notes it on the report. Add a value under the Copy deck card is only for testing a specific value or overriding the deck.
Add from files takes a whole round of .html / .eml files at once; each lands on its deck version from the .eml subject, the file name (CI9630_V5_EN.html) or the product code in the email. Each email's version is read from the deck's copy, and the row's version picker is only for the rare tie between versions with identical copy.
The variance log is the developer hand-off: one numbered row per issue with the versions it affects (ALL, V4–V6…), the fix in a developer's terms, and the evidence. On a campaign's Overview, Download variance log sits beside the next step: choose Fails only or Include warnings for the .docx of the whole campaign, every round and every language. On the Report, All versions has the same menu for the round and language in view, and a single report's Share & Export menu has the log for just that round.
Analyzing emails
Home's modes all share the same campaign bar on top:
- Single email: one email at a time.
- Batch: every email of a round at once — versions, Launch / Reminder, every language. Drop the whole round with Add from files, or start from a template.
Any language the copy deck and the email are written in — English, French, Spanish, German, Arabic, Hebrew, Chinese, Japanese and more. Pick the language on the campaign bar: the chips are the client's languages (set in the client's settings → Languages) plus any the campaign already has, and + adds any other.
The deck comparison, creative comparison and every generic check (links, accessibility, rendering, spam, alt text, right-to-left layout for Arabic and Hebrew) work in all of them; an email set to the wrong language is refused with the language it actually reads as. Language-specific typography rules exist for French today — guillemets, non-breaking spaces, currency — and others follow as teams need them.
Drop an .html or .eml file on the Email HTML box, browse for one, paste the source, or paste a preview URL (SendLint fetches it). A .eml — or Outlook web's *View message source* pasted in — is unwrapped automatically, and its subject line is read from the message header. Plain HTML carries no subject, so a Subject line field appears under it: type the subject as sent, or leave it empty and the page title stands in for the subject-line check.
A copy deck is the approved copy: a Word document (.docx), a Pages file, or a PDF — including a designed PDF exported from a review tool, read from its layout. Attach it on the Copy deck card and SendLint compares the email against it line by line — subject, pre-header, headline, body, CTAs, legal, alt text and links — in each language the deck has a column for: English, French, Arabic, Spanish, any language SendLint knows. Decks with Launch and Reminder version tables and one column per language are understood natively. Copy and links in separate files? Tools → Prepare a deck combines them into one deck first.
The moment a deck is attached, SendLint parses it and shows an inline review: how confidently it read the deck, which versions it found (Launch v1, Reminder v2…), which languages, and the exact copy per section it will compare — in every language the deck carries. If the deck has multiple versions, tell it which one this email is (or let it auto-detect from the email's own copy). No more discovering a mis-read deck after the report is generated.
Attach the deck with a Campaign ID filled in and it saves to that campaign on its own — the deck review shows Saved for <campaign> — and future analyses of the campaign reuse it automatically, no re-uploading each round. The creative works the same way. Every deck-compared report states which deck it was checked against in the header ("Compared against <file> · reused deck"), so there's never a question of what the copy was verified with.
The creative is the approved design — a PDF, a PNG or JPG export (Figma), or an Adobe XD file; drop two images (desktop + mobile) and they're paired automatically. Attach it on the Creative card (same name in every mode) and it becomes the reference for the report's block-by-block design comparison: SendLint matches the right page of a multi-page deck to your version and device, then compares the built email against it module by module. A PNG or JPG has no text layer, so text-based creative checks (copy in the creative, placeholder masking) are unavailable for it; the block-by-block compare and the AI visual review still run. See Visual Rendering & Design Compare.
Open any saved report and click Re-run in the action bar — SendLint re-parses the stored HTML and runs the analyzers again using the current rule set. Useful when you've updated brand rules or want to apply newly added checks to old reports without re-uploading.
Pass: the check ran clean. Fail: a defect to fix. Warn: worth a look but not blocking. Skipped: the check legitimately couldn't be evaluated (for example a deck section wasn't provided). Skips are counted apart and never as fails; they aren't listed on the report, and the exported PDF names them under Not run. A WARN with a POLICY pill means the client's check policy demoted what would have been a failure; the details note explains it.
One issue, one finding. When two checks see the same issue, it is counted once, under the check that says most, and the other check says where it is listed. A link that lands on an error page and whose URL also differs from the deck's is one finding under Landing Pages, which gives both facts; a wrong subject line is counted under Title Matches Subject Line, not again under the subject line's deck check; a spelling slip on a line the deck check already fails is that check's finding.
Copy the approved deck wrote. When a brand or accessibility rule is broken by copy that matches the approved deck (a superscript on the wrong side of a period, two links the deck sets too close together, a subject line over 60 characters), the check does not fail or warn: it adds a blue note saying the deck has it that way, to raise with whoever owns the deck. The note is not counted against the build, and anything else the check found still is.
You don't type a version. SendLint reads which deck version each email is from its own copy (and, in a batch, from the .eml subject or file name). In Batch, each email's ⋯ settings ask one question — Launch or reminder: Auto / Launch / Reminder — where Auto lets the deck decide; pick one only when the deck has both and the email could be either. The row's version picker is for the rare tie between versions whose copy is identical. Optional A/B variant and Audience labels name the report without changing the checks.
Tokens like %%FirstName%% or <Firstname> are read automatically: SendLint matches each token against what the deck and the email say (a deck placeholder against the rendered test send, or a merge tag against the deck's filled-in text) and notes the result on the report's Personalization card.
Under the Copy deck card, Personalization tokens → Add a value sets a specific test value or overrides the deck — type the token as your platform writes it.
Every major ESP syntax is recognised: Salesforce Marketing Cloud %%FirstName%% and AMPscript, Handlebars {{first_name}}, Liquid (Klaviyo, Braze, Customer.io, Iterable, HubSpot, Marketo), Mailchimp *|FNAME|*, Campaign Monitor [firstname,fallback=there] and Salesforce {!Contact.FirstName}. Tokens that differ by language take separate EN and FR values.
Built a batch structure you'll reuse — variants, test conditions, languages? Save it as a template from the Batch panel and recall it next campaign. Templates store the structure only, never URLs or HTML.
Each email in a batch has its own language (EN / FR) — Set all switches every row at once. An email's ⋯ settings hold Launch or reminder, the optional labels, Attach a deck for this email (it replaces the shared deck for that one email) and, for plain HTML, its Subject line. The list header says how many emails have no subject line.
Tools
Tools in the top bar holds eight single-purpose utilities that work around an analysis or on their own. Each opens with Try an example (Harbourline, a fictional brand) so you can see what it gives back before using your own files. On a phone, All tools above a tool's title goes back to the list.
Drop a copy deck (Word, Pages, PDF or a designed PDF) together with anything holding the rest of the campaign: a links spreadsheet (.xlsx / .csv) or a separate deck for another language. SendLint reads each file, puts the sheet's links under the versions and languages each row names (no version = every version; no language = all of them), takes a separate deck in another language as that language's column, and says what came from which file. Download in SendLint format writes it all as one .docx with a full link matrix.
When the parser isn't confident (or the result isn't what the deck says), Let the AI Agent read it: one click.
If the deck's structure read fine and only its section labels are in a language SendLint doesn't know (Asunto, Betreff, سطر الموضوع), a small, fast model classifies just the labels — only the labels are sent, and the copy stays the parser's. Otherwise the deck's text goes to the AI Agent, which returns the same structure — versions, languages, sections — plus a short summary of how the deck is organised and anything odd in it. Every line it returns is checked against the deck's own text; anything not in the deck is dropped and counted. You can switch back to the parser's read at any time.
Drop the earlier deck and the newer one. Every changed, added and removed line shows version by version and language by language, with the changed words marked; a translation that only arrived in the newer deck folds into one summary. Save as PDF prints the page as it looks, on white, for the round's record.
Drop images — screenshots, design exports, photos — and say in a few words where each goes, or switch to A whole email. The AI Agent writes alt text the way email teams do: one short sentence on what the image shows ("Family shopping for groceries together in a supermarket."), logos and icons named for what they are ("Harbourline logo.", "Shopping cart icon."), a banner's own words, and alt="" for decoration or for words the copy beside it already says. Written in the email's own language (French is Canadian French); one click per run.
Link sheet follows every link to where it lands — status, redirects, page title, tracking parameters, error pages and test sites; unsubscribe links are listed but never opened.
Image check reads every image's file size, format and pixel size against the size it's shown at, plus missing alt text.
Image optimizer takes the images themselves and gives each back at the size the email needs — the shown width, doubled for retina — as a JPEG or PNG, with the size before and after; it runs in your browser and uploads nothing.
Screen reader transcript reads the email the way a screen reader does, line by line: the pre-header that is off screen but read aloud, images read by file name, tables announced cell by cell and links nothing names.
Subject & pre-header preview shows where six desktop and phone inboxes cut the subject and pre-header, measured in each inbox's font.
The tools hand work to each other in one click: under a Link sheet, Image check, Screen reader transcript or Alt text writer result, This email in: opens the same email in another tool; Image check's write it with the Alt text writer → opens the email's images there; Deck compare's Prepare the newer deck → and Prepare a deck's Compare it with an earlier version → carry the deck across. Results aren't saved — download or copy what you need.
Each tool has a public page at sendlint.com/tools showing what it does with a real example. The Subject & pre-header preview runs entirely in the browser, so anyone can use it without an account; the rest need a SendLint sign-in.
Visual rendering & design compare
Every report with an attached creative gets a Compare to the creative view (it's the default tab of Visual Rendering whenever a comparison exists). At the top: the approved creative and the built email side by side, with the verdict that matters — "N of M blocks match the creative." Below: every block of the email, top to bottom, as one row each, saying whether it matches or what differs. A difference measured the same on desktop and on mobile (the hero image 22% narrower on both) is one finding in the report, marked "desktop and mobile". Open a row to see that block beside the matching part of the creative. The blocks come from the email's own structure — hero, body copy, example block, steps, CTA, legal — the same granularity your copy deck uses, so nothing is chopped mid-paragraph.
✓ matches the creative — the block reproduces the design; move on.
differs (~N%) — every differing block also says *why*, deterministically. The two sides are read as text first: the email's paragraphs and their rendered lines are matched word for word to the creative's lines, so a block says exactly which paragraph or line only one side has, how many lines a paragraph takes on each side and why ("set smaller than in the creative (11 px against about 14 px)", or the wording differs), a divider only one side has, a button that sits centred where the creative sets it at the left, or a paragraph centred where the creative sets it left-aligned (each side's alignment is read from its own lines, so a paragraph of lines of near-equal length is never called either way; a one-line heading is read against the text column under it, flush with its left edge or centred over it, and on the email side by its own text-align setting; a heading as wide as its column is never called), or copy set bolder or lighter than the creative (the email's font weight against the weight the creative's font name says, such as "Semibold" or "Light": 200 apart or more, and never for a font whose name gives no weight: a creative exported from Figma names one font for all its text, so its weight is not compared). An email in another language than the creative (a French email against the English creative) has no words to match, so its paragraphs and headings are paired with the creative's by where they sit, and only their alignment and weight are compared. An image is sized against the creative's placement of it; a picture the creative draws as artwork rather than placing it as an image is measured by its visible extent on both sides instead.
Where there is no text to read, the pixels say it: "horizontal padding differs", "vertical spacing differs", or "content height differs sharply — a module may be missing, added, or stacked differently". The percentages are approximate and never change the report's pass / fail — this is a QA assist that shows you exactly where to look.
Three kinds of noise that plague naive pixel-diffs are excluded automatically:
- The agency mockup chrome — the fake inbox header (subject line, "To: Firstname Lastname") at the top of creative PDFs is cropped off before comparing.
- Dynamic placeholders —
<MMMM DD, YYYY>,<Firstname>,<XXXX>regions in the creative are excluded from scoring, so a resolved date or merged name never reads as a difference. - FPO / DRAFT watermarks — proofing stamps are detected and ignored.
The first two read the creative's text layer, so for an image creative (PNG or JPG) they are unavailable — every block is compared as is; the watermark filter, the block-by-block compare and the AI layout review still run.
Copy differences are also out of scope by design: copy fidelity is the deck comparison's job, checked line by line elsewhere in the report.
The compare view has exactly two sides — Desktop and Mobile — matching the two pages a creative deck actually carries. If the deck includes a mobile page, SendLint renders the email at the mobile width and runs the full block-by-block comparison there too; flip between them with the Desktop / Mobile buttons. No mobile page in the deck? The desktop comparison is shown with a note.
When a creative is attached, an AI model looks at the creative and the built email together and reviews layout only — spacing, alignment, sizing, image crops, module order — grounded in the block results so it focuses on the blocks that actually differ. It runs automatically, once, with the creative comparison, when the client's AI Agent setting has the visual review on.
Run AI visual review on the report's Creative tab covers the times it didn't run or is out of date: reports from before it ran automatically, a run when the monthly AI budget was used up or the AI was unavailable, and after you re-run the comparison against a new creative. Once a report has one it's saved and shown every time, for everyone; it isn't run again on the same email and creative, and re-running the comparison keeps it.
It reads like the rest of the report: each difference is one row, and opening it shows what the creative has and what the email has. Desktop and Mobile have a tab each, the differences it confirms come before its own notes, and a picture in another language is called out in red at the top.
Each difference it sees itself counts in the report as a warning, never a fail, under the check it belongs to: a heading set bolder than the creative under Text Size & Wrapping vs Creative, a heading centred where the creative sets it left-aligned under Alignment & Centering vs Creative, and so on. Anything no other check covers (modules in another order, a different picture, a band's background) is listed under AI Visual Review. Every such line starts with "AI visual review (not measured)", so you can tell it from a measured difference, and carries the AI's sentence in full. Each issue is mentioned once in the report: every sentence that names a difference is read on its own, a sentence naming two differences (a heading bold and centred) is one finding, under the first one nothing else has counted, and two sentences about the same thing (the rating labels set smaller, said once for desktop and once for mobile) are one finding quoting both; a difference the comparison measured on that block already, or that another check flags (Words in Pictures Language failing the same picture), is not mentioned again; and one seen on desktop and on mobile is one finding saying "desktop and mobile". When the AI confirms a measured difference, that finding says "The AI visual review saw this too." Its verdicts on the measured differences never cancel one.
It never comments on text content (that's the deck's job) and counts against the monthly AI budget.
An instant, script-blocked live render of the stored HTML. Pick an email client chip — Desktop webmail, Apple Mail · iPhone, Gmail app — or any device width from the dropdown. The Gmail chip carries a real number: Gmail clips messages over ~102KB, checked against this email's actual size. Each browser chip says exactly what it simulates.
The two Outlook chips, Outlook 365 · Windows and Outlook 365 · dark, are different: they open the email in classic desktop Outlook on a Windows machine SendLint runs and show that capture in the preview's place.
Under a capture, Check this render has the AI Agent compare it (and the dark capture, if you've rendered one) with the same email in a browser and list what Outlook breaks: a button that loses its shape, a missing image, stacked columns, a logo lost in dark mode. Each issue opens its spot in the capture so you can check it by eye. SendLint runs its own rendering pipeline and won't show you a fake screenshot of a client it didn't run.
Outlook for Windows renders with Word's engine, which no browser preview can imitate, so SendLint opens the email in classic desktop Outlook from Microsoft 365 Apps on a Windows machine it operates, in light and dark mode, and captures the result. The first render takes about a minute; later views are cached, and Re-render forces a fresh capture. The static Word-engine checks — border seams, missing VML fallbacks, GIF first-frame issues, line-height-zero superscripts — still run on every report under Code checks. Headline Wrap in Outlook (Font Fallback) is a prediction, not a render: Outlook for Windows can't load a web font and sets the text in the stack's Windows font, usually the wider Arial, so SendLint sets each headline of 20 px or more in Arial's character widths, in the width Outlook gives it, and warns when a word would sit alone on a line or is one rounding away from it. It covers Outlook 2016 to 2021 as well as 365, which the capture alone does not. Round 2+ reports can pixel-diff the current Outlook capture against the prior round from the same panel.
Re-run comparison regenerates the whole comparison from scratch — use it after a new creative version or when you want current-engine results on an older report. An AI visual review of the same email and creative is kept, not run again. Done with the visuals? The section header's Hide control collapses all of Visual Rendering (the block verdict stays visible in the header), and the choice is remembered.
Campaigns, folders & sharing
Every analysis with a Campaign ID joins that campaign. Campaigns in the top bar lists every campaign — its client, where each language is, whether it's signed off, and what moved last — and on New analysis the Campaign ID field lists your recent campaigns: pick one to add a version or a round, or type a new ID to start one. Inside a campaign, the Campaigns handle on the left edge opens a quick-switch list without leaving the page.
When you analyze emails with campaign IDs, SendLint automatically creates a folder for that campaign and groups all related versions together. This makes it easy to see all Launch / Reminder versions side by side.
Click a campaign on the Campaigns page, or its folder row in the campaign list (the Campaigns handle on the left edge of an open campaign), and its workspace opens on the Overview: whether it can be sent, the next step, what blocks sign-off and who has to act, and the files the campaign is checked against.
On a campaign with several versions, the Report tab lists every version with its fails and warnings, with All versions at the top for every finding merged across versions. A campaign with one email (in one or more languages) opens straight on its report, rendering and creative comparison included, with its Round and Language as one line above it: pick every language, or All rounds, for the findings merged into one list.
In the list, the chevron beside a folder expands the tree in place instead, when you just want to scan rounds and variants. The workspace has a real URL, /campaigns/<campaign-id>, that you can refresh, bookmark, or share with a teammate.
In the campaign list, use the ⋯ menu on any report row to rename it or move it to a different folder, and hold the delete control to remove — a quick click never deletes. Multi-select with the row checkboxes for bulk moves and deletes.
A campaign's Overview says where the campaign stands. It is written for the producer or account lead, the person who forwards it; the QA's workbench is the Report, where signing off, starting a round and writing fixes are done. Top to bottom:
- Can it be sent: the verdict in one line (for example Not ready to send) with what it rests on.
- The rounds as a timeline: what was open in each round as a figure over the round line and, beside the latest, how far it moved since the round before. That change is counted over the emails both rounds ran, and it says so when that is not all of them ("↓ 26 in English"). The line runs on to sign-off, and into the SendLint mark once the campaign is signed off.
- A row per language: its fails, warnings and passes in every round, and where it stands (Needs fixes, Ready to sign off, Signed off) on its own latest round.
- Next step: the one thing to do now: send the fixes to the developer (with Download variance log), check something by eye, ask the client, or open the Report to sign off.
- What blocks sign-off, numbered in the order to fix it and grouped by who acts: For the developer (wrong in the build), Check by eye (the checks can't be sure: words read from a picture, links a bot-block hid) and Questions for the client. Legal and wrong-destination problems come first, then copy that differs from the deck, then the rest. Every line opens its evidence in the Report, where All versions has Write the fix for every version on each check the developer has to fix.
- Ask the campaign · Versions · Sources · Past campaigns: one switch under the list. Versions (campaigns with more than one) shows every version per language, clean or failing, each opening its report. Sources is the deck and creatives the campaign is checked against. Past campaigns appears only when this campaign differs from the client's earlier ones.
The summary line is the AI Agent's when the client's AI Agent setting lets it write the brief (Clients → settings → AI Agent, on by default): it reads the round's findings, not the emails, and every number in it is checked. Otherwise it is written from the findings; Summarize with the AI Agent writes it on a click. (The Overview was called Summary before October 2026.)
When you run a Round 2 (or later) report on the same campaign, SendLint compares the current run against the previous round. The report view shows the round diff — issues fixed since last round, new issues introduced, and unchanged issues that still need attention. Rendered screenshots are pixel-diffed too.
Every campaign is Active until it's marked Complete. The Campaigns page filters by Active / Completed / All, and the campaign list splits the same way. Open a campaign's ⋯ menu in the list and use Move to Completed / Move back to Active (it applies instantly — no page refresh). This only files the campaign; it doesn't sign off a round or mint a certificate. This is a campaign-level decision, deliberately separate from per-round QA verdicts, so signing off R1 doesn't shelve a campaign that's still being worked.
Deleted reports sit in Recently Deleted at the bottom of the campaign list for 30 days before they're purged permanently. Press Restore to bring one back — it returns to its campaign's group (or beside your folders if its folder was deleted in the meantime).
Every campaign round has a Round brief — open a campaign's Round matrix and press Round brief. It summarizes what developers need to fix, with their HTML context: copy it into Slack or an email, download it, or create a public read-only link. Share the URL with anyone (no SendLint account required on their end). Revoke the link at any time from the report's action bar.
Rounds & sign-off
Two ways. Fastest: open the current round's report and press Start R2 · this email in the header. Its dialog lists every email of the round, so one press can start one of them or all of them: paste the revised HTML and SendLint re-analyzes it as the next round, inheriting the campaign, variant and client. Or start from Home with the same Campaign ID: the round is worked out for you ("Round R3 · auto — CI1234 is at R2"), and Change overrides it on the same line. Round 2+ triggers delta tracking: findings are matched across rounds, so fixed, still-failing and regressed issues update automatically. Landing-page reports don't participate in round tracking.
A campaign's Round matrix tab tracks one version's findings round by round: did the developer fix what you reported, what's still open, what came back. Pick the version (or, for one email in several languages, the language) at the top.
Findings sit in the same category cards as the report; Show (All · Fail · Warn · Fixed) counts and filters. On a tablet or wider, each finding is drawn as a track across the rounds: a solid dot is a fail, a ring is a warning, and a tick marks the round it was fixed; the word beside the finding says where it stands now. With a single round there is no track yet, only the word.
The line across the top is the round signal: one beat a round, taller when more was open, running on to sign-off and into the SendLint mark once the round is signed off.
Click a finding for its round-by-round history and comment thread. View as switches between QA (everything), Developer (only what still needs fixing) and Client (a short status summary). The matrix is read-only: waive a check, or add a finding SendLint missed, in the report.
Four words, all worked out by SendLint from each round's email — nobody sets them by hand. Each round reads Fail or Warn (flagged, at that severity), Pass (checked and not flagged, and never flagged before — an issue that first appeared in R2 reads Pass in R1) or Fixed (not flagged any more, after being flagged earlier). The latest round's column (R3 · latest) is where it stands now: Fail, Warn or Fixed. A fix that comes back reads Fail or Warn again, tagged "Came back in R3". Findings on checks waived in the report aren't tracked in the matrix.
Sign-off lives on the report, in its header, and the button says what it completes: Mark campaign complete on a single-language campaign; on a campaign with more than one language, each language's report has its own button, Mark EN complete (the other languages stay open) and, for the last language, Mark AR & campaign complete. Each one signs off that language's own latest round, even when the languages sit on different rounds.
The campaign Overview shows where each language stands and, when nothing blocks, sends you to the Report to sign off. Signing off writes an audit-log entry with your user and timestamp, and sends a round brief to Slack if the client has a webhook configured.
This is a QA statement about that round; to shelve the whole campaign, use Move to Completed in the campaign's ⋯ menu in the campaign list (a separate, campaign-level status). You can re-verdict a round later if a regression appears; the audit log records every change.
A campaign with more than one language is signed off per language: the campaign Overview has one row per language (English, French, Arabic…), each on that language's own latest round with its own status, and that language's report has its own Mark … complete button. Its certificate covers that language only, and approving one language never replaces another language's certificate. A language still on an earlier round keeps its own row, so it can never drop out of view.
In a report's Share & Export menu, Export report (PDF) downloads one document for that report, with no options to set. It opens with the counts, then lists what failed and what is a warning in full: each check with what it found and the evidence for the findings that did not pass (lines that passed inside the same check are counted, not listed). After that come the checks that passed, by name under their category, anything waived with its reason, and a short list of the checks that were not run because the email had nothing for them to check.
On a campaign's Overview, open Download variance log beside the next step and choose Fails only or Include warnings: the .docx covers the whole campaign, every round and every language.
It holds one numbered row per issue, the versions it affects (ALL, V4–V6, Launch, EN/AR…), the change in a developer's terms and the evidence. Each row says what is wrong once: for copy, the difference itself (a word the email adds, a ® on the wrong word) with the deck's sentence over the email's and the changed words marked.
Fails only is the must-fix list, followed by the strong design and rendering differences from the creative comparison and the AI visual review; Include warnings adds the warnings and every such difference. On the Report, All versions has the same menu for the round and language in view, and a report's Share & Export menu has the log for just that report's round.
The matrix header's "Compliance PDF" downloads a signable PDF of every audited action on the campaign — sign-offs, finding status changes, comments, manual findings, brief sends — in chronological order, rendered in your profile timezone. Every time carries its zone (UTC when your profile sets none), each action says who did it and what they typed with it (the note on a dismissed finding, what a missed finding said), and every page names the campaign and its page number. This is the artifact to attach to a campaign's approval record.
Open a campaign's Round matrix: every finding by round — fixed, still open, regressed, new — with its status. The report header also shows this email's progress across rounds (fails and warnings per round, and how many were fixed or are new since the last one). The Round brief for the developer is in the Round matrix too.
From the round matrix, use "Import bug log (CSV)". The file needs a description column (status and notes are optional). SendLint previews every row as matched (an existing tracked finding — shown with a similarity score), ambiguous (you decide), or new (created as a tracked finding). Nothing is written until you confirm. This is how teams bring years of spreadsheet bug logs into round tracking.
Press "+ Missed finding" above the findings on any campaign report — or + Add a missed finding at the bottom of a category, which picks that category for you. Say what's wrong, choose Fail, Warning or Note, and optionally paste where it is in the email.
It shows on the report in its category, marked Added by QA; it goes into the variance log for the developer (fails and warnings — notes stay out); it's tracked across rounds in the Round matrix; and it feeds the AI Agent's per-client context so patterns you flag by hand inform future reviews.
To change one, press Edit on it. If it turns out not to be an issue, press Waive — it moves to the category's Waived section (with Restore) and leaves the variance log. Delete finding (inside Edit) is for one added by mistake. Every add, edit, waiver and deletion is in the campaign's audit trail.
SendLint Approved
SendLint Approved means three things about a round's emails:
- Earned — the round passed your client's compliance policy at approval time (zero unresolved fails by default; waived findings count as resolved).
- Frozen — approval minted a certificate (id like
SL-2026-XXXXX) recording the SHA-256 of each approved email's exact HTML, the check counts, waivers, and policy in force. - Verifiable — anyone holding the certificate id can open /verify/<id>, paste the HTML SendLint checked (the same file, not a copy the email platform personalised for one reader), and confirm it's byte-for-byte what was approved. Any post-approval edit — a tracking pixel, a typo fix, a swapped link — produces a different hash and voids the match.
Approval is earned, not clicked. If the round has unresolved failing checks, the approve action returns the exact blockers, listed under the round control. Three paved paths:
- Fix the issue and re-run the round
- Waive it — waive the check on the report, or waive it client-wide for a standing false-flag (e.g. legal copy that lives in a separate master deck). Waivers ride onto the certificate.
- Override — approve anyway with a typed reason that goes on permanent record: the audit log, the Slack ping, the compliance PDF, and the certificate all carry it.
For clients that need a second set of eyes, enable two-party approval in the client's compliance policy. Then a Member's "Mark … complete" becomes an approval request — the round doesn't move, a Reviewer seat gets pinged on Slack, and only a Reviewer can grant (or override) the approval. Certificates record how approval happened: two-party (requested by X, granted by a Reviewer) or self-approved — labeled honestly either way, including on the public verify page.
- Certificates in the top bar: every signed-off round in one list. Open one and it shows beside the list, its row marked, with a link to its public page
- Approval response + Slack ping — the cert id and a View-certificate button arrive the moment a round is approved
- /verify/<certId> — the public page: approval facts, masked approver, per-email hashes, and the paste-to-verify box (hashing runs in the visitor's browser; nothing uploads)
- Client portal — approved campaigns show the seal badge linking to the verify page
- Compliance PDF — a certificates block with the full hash list and verify URL, so the signed paper binds to exact bytes
A new approval supersedes the old certificate; leaving approved revokes it. History never deletes — a superseded cert page names its successor.
The strongest guarantee: make your send pipeline ask SendLint before every send. Hash the final HTML (SHA-256 of the exact UTF-8 bytes, hex) and call:
GET /api/v1/verify?hash=<sha256> · Authorization: Bearer sl_live_...
Responses:
verified: true, status: "valid"— this exact file is on a standing certificate. Send.verified: false, status: "not_found"— never approved, or edited after approval. Block.status: "superseded"— an older approved version; a newer approval replaced it. Block, send the current one.status: "revoked"— approval was withdrawn. Block.
Keys are the same self-serve API keys as /api/v1/analyze, scoped to your workspace.
In Salesforce Marketing Cloud, gate a send on the certificate in three steps:
- Hash the final HTML. In an SSJS Script Activity, load the exact HTML you're about to send (the same bytes that were QA'd — pre-personalization) and compute
SHA256(html)— AMPscript's SHA256() and SSJS both produce the hex SendLint expects. Personalization strings like %%FirstName%% are fine as long as you hash the same template bytes SendLint analyzed.
- Call the gate.
HTTP.Get("https://<your-sendlint>/api/v1/verify?hash=" + hash)with yourAuthorization: Bearer sl_live_...header.
- Branch on `verified`. true → proceed to send. false → stop the automation and alert the team with the returned
statusandmessage(they say exactly why: never approved, edited after approval, superseded, or revoked).
The same pattern works in any CI/deploy pipeline: openssl dgst -sha256 email.html then curl the gate.
AI features
On any saved report, open AI Agent → AI Review in the action bar. The AI Agent reads the email and the rule findings and returns:
- Issues the deterministic rules missed (must-fix / should-fix / nice-to-have)
- Findings that are probably false positives in context
- With a deck attached, section-by-section copy-vs-deck notes
- A short summary
The result shows inline; run it again after the email changes. It never changes the report's pass / fail.
On a saved report, open AI Agent → AI Code Revision. The AI Agent reads the email's HTML and the report's findings and proposes fixes as exact edits: this text in the HTML becomes that. SendLint then applies each fix to a copy of the email and runs the checks again, with the same deck and brand rules. A fix is shown only if its check has fewer findings afterwards and no other check fails because of it. Fixes are also re-checked together, so the whole set holds.
Nothing changes until you decide: Accept or Reject each fix (or Accept all). Once every fix is decided, Download the new HTML gives you the email with the accepted fixes applied. Export for developer (PDF) opens the print dialog on a table of the accepted changes (choose Save as PDF): where each one goes, what to find and what it becomes, in the email's own language, and what was left to a person. Decisions are saved on the report, and the result stays on it: reopening the report shows it again without another AI Agent run. AI Code Revision is in beta: read every fix before you accept it.
If a fix lets another check notice something new, it says so. For example, correcting a headline to the deck's words lets the style check match it and ask for bold.
What it leaves alone: link URLs and tracking (fix those in your ESP), merge tags, copy that isn't in the deck, and anything that needs a decision. Those are listed under Left to a person, with the reason for each. The report itself never changes; re-analyze the fixed HTML to get a new report.
Brand Voice AI compares an email's copy against your client's reference samples to flag tone, vocabulary, structure, or formality drift.
- Upload 3–5 representative HTMLs at Clients → [client] → Brand Voice Reference Samples
- Run an analysis with that client selected so the report ties back to it
- On the report, open AI Agent → AI Brand Voice in the action bar
Results show alignment verdict (aligned / drifting / off-brand) plus per-dimension drift.
Deterministic rules run on every analysis — instant, no AI. Nothing goes to the AI Agent unless you ask for it: every AI pass is a click, or follows one of the client's AI Agent settings (Clients → settings) — on by default, off for a client whose contract restricts third-party AI. These use it:
- AI Review — a click on the report
- AI Brand Voice — a click on the report
- Outlook render check — a click under a real Outlook capture (Check this render): the Outlook captures (light, and dark when rendered) and a browser render of the same email are sent; the AI Agent lists what Outlook breaks, to check by eye
- AI Code Revision — a click on the report (AI Agent → AI Code Revision): the email's HTML and its findings are sent; the AI Agent proposes edits, and SendLint applies each one and re-runs the checks before showing it
- AI visual review — the switch next to the creative, per run (Single) or per batch, pre-set from the client's AI Agent setting
- Words in pictures — the switch next to the copy deck, per run or per batch, pre-set from the client's AI Agent setting: the email's pictures (a hero headline, product tiles, an image button) are read so their words are checked against the deck like live text
- Spelling & grammar — every analysis, when the client's AI Agent setting allows it (on by default): the email's visible copy is proofread in its own language by a small, fast model; slips show as warnings, never fails, and the client's trademarks and business names are never flagged. A slip on a line the copy deck check already reports as different from the deck is listed there only: the deck says what that line should read
- Ask the campaign — a question typed on a campaign's Overview: the campaign's findings are sent (never the emails), and every sentence of the answer is checked against them before it's shown; answers are saved for the team
- Campaign brief — on a campaign's Overview, once a round is in, when the client's AI Agent setting allows it; otherwise a click on Write the brief. Only the round's findings are sent, never the emails
- Brand-guide import — when you upload a guide PDF on a client's Brand Rules; nothing saves until you review it
- Alt text writer — a click in Tools
- AI deck reader — a click on Tools → Prepare a deck when the parser isn't confident; every line it returns is checked against the deck's own text
- Label classifier — the same click, when only the deck's section labels are in a language SendLint doesn't know; a small model maps labels to roles and only the labels are sent
Once per round. A round's email doesn't change, so every result is saved and shown to the whole team on every visit — a second click reads it instead of running the AI Agent again. It runs again only when what it read changed: the next round's email, a new Outlook capture, another creative, a waived finding, new voice samples, or a new question.
Each counts against your workspace's monthly AI budget: 5,000,000 tokens per paid seat, or the cap set in a client's Spend budgets. Settings → Usage shows this month's use by feature against the budget.
SendLint Cloud has the AI Agent configured for every workspace. Self-hosters set ANTHROPIC_API_KEY in the server environment; without it, AI runs are refused with a note saying so, and the AI visual review box is unavailable.
After analyzing any email, open the report's ⋮ menu and choose Save this email's styles to the client's brand rules. Open it and SendLint shows you the colors, fonts, sizes, and weights it found in the email — picks with high confidence are pre-checked. Tick the ones you want and click Apply. Picks merge into your client's brand_rules without overwriting anything you've already configured.
Useful when you start with a real-world email and want SendLint to flag future emails that drift from it.
Two passes feed the Style Review picker:
- Layer 1 is instant — it reads the email's declared CSS (inline styles +
<style>blocks) with a server-side parser. - Layer 2 runs in headless Chromium with the email actually rendered. It resolves em/% sizes to px, captures inherited cascade values, picks up
:hoverstates, and confirms image-background colors. Costs one render budget unit per first-reviewed report; cached after that.
When the badge flips from "Computing exact styles…" to Layer 2 ✓, the picks re-render with tighter confidences — more get auto-checked at the 0.8 threshold. Your prior selections survive the swap.
Setting up your workspace
First-time tenants land on /onboarding, a 5-step wizard that walks you through:
- Workspace — name your team / org
- Brand — create your first client and pick a starter rule template
- Sample email — paste an email's HTML so we have something to analyze
- Run a check — see the analyzer end-to-end on real data
- Invite teammates — optional; you can skip this and add seats later
A progress checklist stays on New analysis until all 5 steps are done. You can skip a step and come back to it — your progress carries forward.
Brands are configured under Clients → New Client. Pick a starter template (Empty or Generic Marketing) to seed sensible defaults, then customize the palette, fonts, spam settings, and link rules. The Settings page is the source of truth — any analysis run against this client uses the rules you've configured there.
If a wizard step fails (network blip, RLS hiccup), you'll see an inline error and you can retry. The wizard never marks itself complete until your workspace actually has at least one brand and one analysis — so a noisy network won't lock you into an inconsistent state.
Client configuration
Go to the Clients page and click "New Client". Give the client a short name that identifies them in your account. The client profile stores brand rules and check preferences that are applied every time you analyze an email for that client. A client opens on Sources, followed by Brand rules and Checks: the order to set it up in. Import the brand guide or a sample email, review the rules read from them, then choose which checks run.
When creating a client you can pick a starter template:
- Empty — No defaults; fill everything in as you go
- Generic Marketing — Conservative defaults for typical email programs (font sizing, spam thresholds, color contrast, etc.)
Pick the closest fit and adjust from there.
In a client's settings (Brand Rules tab), you can configure:
- Layout: Desktop / mobile widths
- Typography: Allowed fonts, header / CTA font weights, min sizes
- Colors: Brand palette, background color, section-specific colors
- Links: Owned domains, blocked domains, language specificity
- CTA & Copy: Sentence case, grammar rules, word order rules
- Logo Rules: Dual-logo separation, partner brand names
- Image Rules: Max file size, border / width requirements
- Business Names: Names that must appear in correct case
- Trademark Fidelity: Terms that must always render with the correct trademark symbol (or without)
- Deliverability: Caps ratio, trigger phrases, image-to-text ratio
- Code thresholds: Pass / warn similarity thresholds for screenshot diffs
- Languages: the languages the client sends in (the chips offered first on every analysis screen)
- Bilingual Detection: EN / FR word hints
On a client's Sources tab (the one it opens on), upload the brand-guide PDF and SendLint extracts colors, fonts, widths, and spacing into the Brand rules form. Every extracted value is listed with the page it came from so you can spot-check before saving — editing a field clears it from the review list. You can also extract styles from a pasted sample email, or copy rules wholesale from another client. Nothing persists until you review the change list and Save.
Brand Rules is 18 sections deep. Use the search box above the sections — it matches section titles and field keywords (try "font", "palette", "utm", "superscript") and jumps you straight there. Each section has its own Reset with an Undo toast, and the header shows who last saved the client and when.
Each check on a client's Checks tab has three states. On runs at full severity. Warn keeps it running but demotes failures to warnings — they don't count toward the fail total, and the report shows a POLICY pill on demoted results. Off skips the check for this client entirely. Checks are grouped by category with search, category master toggles, and Expand/Collapse all. Use Copy-from-client to apply one client's configuration to another, and Reset defaults to start over.
That check's analyzer only runs when its Brand Rules values exist — Brand Color Compliance needs a palette, Grammar Rules needs rules. Enabled with empty configuration it would silently do nothing, so the badge warns you. Click it to jump to the exact Brand Rules section that feeds the check.
Waiving a check on a report moves it to that report's Waived section and out of its totals. Waiving at the client level does the same on every report for that client — those appear in a "Waived from reports" list on the Checks tab, where you can restore them or turn the waiver into a disabled check. Waived checks still run; they just don't count.
When your team keeps waiving the same check for a client (5 or more times, in 2 or more campaigns), the client's Checks tab proposes the rule that says so, with your team's own reasons quoted.
Where the waived findings say exactly what's accepted, the rule is that narrow: a word the spelling check keeps flagging goes in the client's dictionary, a deck line that keeps being reported missing becomes one of the client's deck lines that are instructions, not copy, a font joins the allowed list, a text size becomes the minimum. Otherwise it's the check itself: a warning instead of a failure, or off for this client.
Checks of the email against the deck (legal copy included), links and the unsubscribe link are never proposed as a warning or off. Apply puts the change in the form, and it's reviewed and saved with the rest of the client's rules; Not now hides it.
Under Clients → [client] → Brand Voice Reference Samples, paste 3–5 representative HTMLs that exemplify the client's voice. These power the Brand Voice AI pass (see AI Features) — the more representative the samples, the better the drift detection.
Integrations
Every report carries the Visual Rendering section: a Compare to the creative view that checks the built email block-by-block against your approved creative, and a Render tab with an instant live render at any device width plus per-client simulations (Desktop webmail, Apple Mail, Gmail — with its 102KB clipping check) and real desktop Outlook 365 on Windows, light and dark, captured on a machine SendLint runs. SendLint runs its own rendering pipeline rather than integrating a third-party cross-client provider — every browser simulation is labelled as one. Full tour under Visual Rendering & Design Compare.
Go to Clients → your client → Settings → Brand Rules & Settings → Notifications and press Add to Slack. Slack opens its own channel picker — choose the channel, click Allow, and you land back in SendLint with "✓ Connected to #your-channel". The webhook is acquired automatically and stored encrypted; you never see or handle a URL.
What arrives in that channel: round status changes (needs fixes / approved) with a link to the round matrix, approval requests under two-party policies, approvals with the certificate id and a View-certificate button, override warnings with the typed reason, and @mention pings from comments.
To switch channels later, press Reconnect Slack and pick a different one — the newest install wins. Manual fallback for IT-locked workspaces: create a Slack app with an incoming webhook yourself and paste its URL into the field below the button; Send test message confirms the wiring either way.
Go to Clients → your client → Settings → Notifications → Webhook. Paste an HTTPS endpoint, tick the events you want, press Generate secret (copy it — it is shown once), then Send test to deliver a ping event and confirm the wiring. Every subscribed event is then POSTed to that URL as JSON.
Events
- analysis.completed — a report was saved. data: { reportId, campaignId, clientId, kind, language, versionLabel, name, roundNumber, counts: { fail, warn, pass, skipped, total }, hasCopyDeck, hasLayoutPdf, reportUrl, matrixUrl }
- round.status_changed — a round moved to in_review, needs_fixes, or approved. data: { campaignId, round, status, previousStatus, notes, reviewer (masked), approvalMode, requestedBy (masked), overridden, overrideReason, certificateId, verifyUrl, matrixUrl, portalUrl }
- round.approval_requested — a Member asked a Reviewer to approve (two-party policy). data: { campaignId, round, status, requestedBy (masked), matrixUrl, portalUrl }
- comment.mention — someone was @mentioned. data: { campaignId, findingKey, variantKey, commentId, mentions, author: { displayName, email (masked) }, excerpt (the whole comment, never clipped), url, matrixUrl }
- certificate.issued — a SendLint Approved certificate was minted. data: { certificateId, campaignId, round, approvedBy (masked), approvalMode, requestedBy (masked), overridden, overrideReason, verifyUrl, matrixUrl, portalUrl, emails: [{ reportId, label, checks }] }
portalUrl is the campaign's public portal link when an active share link exists (null otherwise) — a developer without a SendLint seat can follow it.
Envelope — every POST body is { id, event, createdAt, orgId, clientId, campaignId, data }. id is unique per delivery: dedupe on it, because a retry re-sends the same envelope.
Headers — Content-Type: application/json · User-Agent: SendLint-Webhooks/1 · X-SendLint-Event · X-SendLint-Event-Id (same as the envelope id) · X-SendLint-Timestamp (unix seconds) · X-SendLint-Signature: v1=<hex> — the HMAC-SHA256, under your secret, of the string "<timestamp>.<raw request body>". Until you generate a secret, deliveries go out without the signature header.
Verify a delivery (Node) — read the RAW body bytes before any JSON parsing; re-serialising changes the signature.
const crypto = require("crypto");
function verifySendLint(secret, headers, rawBody) {
const ts = headers["x-sendlint-timestamp"];
const sig = headers["x-sendlint-signature"] || "";
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
return sig.split(" ").some((part) => {
const [version, hex] = part.split("=");
return version === "v1" && hex.length === expected.length && crypto.timingSafeEqual(Buffer.from(hex), Buffer.from(expected));
});
}Retries — each attempt has a 5-second deadline. Network errors and 5xx responses are retried up to 3 attempts in total (about 1 s, then 4 s apart); a 4xx is taken as a definitive no and is never retried. Respond 2xx quickly and do your own work afterwards. Deliveries are best-effort: a failing webhook never blocks the analysis, approval or comment that produced it.
Security — the endpoint URL and the secret are stored encrypted; the secret is never returned by any API. The URL must be public HTTPS — private, loopback and cloud-metadata addresses are refused, including via redirects. Rotating the secret takes effect on the next delivery.
The API is generally available and self-serve. Create a key under Settings → API keys (the avatar menu, top right), then POST your email HTML and a clientId to /api/v1/analyze (every campaign runs under a client; the id is in the client's page address) — the page includes a copy-paste curl quickstart. Keys are scoped to your workspace and can be revoked at any time. The same keys drive GET /api/v1/verify?hash= — the SendLint Approved pipeline gate (see the SendLint Approved section for the SFMC pre-send recipe).
Team & collaboration
Go to Settings → Team (the avatar menu, top right). Click "Invite Member" and enter their email address. They'll receive an invitation email with a link to join your organization. Invited users will share access to all clients and reports within the org. A pending invite has Resend (it rests for a minute after each use, and one invite can be resent at most three times an hour) and a bin: press and hold it for three seconds to revoke the invite.
Two separate dials. Role controls permissions: Admins manage billing, seats, team, and can delete clients; Standard users run analyses and work findings. Seat type controls billing: Member seats are paid and count against your seat limit; Reviewer seats are free and unlimited — right for stakeholders who comment and review but don't run analyses.
Open the round matrix, click a finding, and use the comment thread in the side panel. Replies go one level deep, emoji reactions are supported, and you can attach up to 4 files (10 MB each — images, PDF, or text). Both Members and Reviewers can comment.
Every campaign report also has a general Discussion at the bottom — a thread that isn't tied to any finding, so you can coordinate from Round 1 before per-finding conversations exist. It's one thread per campaign: the same discussion appears on every variant's report and behind the Discussion button on the round matrix. Mentions work the same way (@ + full email).
In any comment — a finding thread or the campaign Discussion — type @ followed by their full email, for example @sarah@yourcompany.com. The mention lands in their Inbox (the Inbox icon, top right, shows a dot when something is unread), and pings the client's Slack webhook if one is configured. You can't mention yourself.
The Inbox icon (top right) collects every comment where someone mentioned you; a dot on it means something is unread. Each row deep-links to the exact finding in its round matrix. Filter unread vs all, mark rows read individually, or mark everything read at once.
Three public links for three audiences. A report share link shows one report read-only (findings and messages, no source HTML or comments). The client portal shows a campaign's round-by-round progress with status counts, deliberately omitting snippets and internal notes. A dev brief shares a round's fix list with a developer. All are tokenized links that expire after 30 days by default and can be revoked; creating them requires a Member seat.
Your subscription includes a set number of seats. Each team member requires one seat. Admins buy additional seats under Settings → Plan & Billing (the avatar menu, top right). When a member is removed, their seat becomes available for a new invitation.
Billing & subscription
SendLint offers monthly and annual billing, per paid Member seat; Reviewer seats are free. Annual billing costs less per month (about 17–19%, depending on the plan). Every plan includes all automated checks, the Tools and team collaboration. Team covers 2 clients and 30 unique emails a month (re-runs and later rounds of an email don't count again); Pro has no client or email limit and adds features such as the AI Code Revision, Outlook renders, batch runs and the API. AI features are included subject to a monthly AI budget that grows with your paid seats. The full billing terms are in the Terms & Conditions.
Go to Settings → Plan & Billing (the avatar menu, top right) to view your current plan, update payment methods, or change your subscription. You can change plan or cancel at any time. A plan change takes effect immediately and is prorated: you are invoiced or credited for the difference. A cancellation takes effect at the end of the period you've paid for, and you keep access until then.
Admins add seats from Settings → Team. Each additional seat is prorated for the current billing period. When you remove a team member, you can choose to keep the seat for future use or remove it to reduce your bill.
Cancelled by accident? While the subscription is still in its paid period, admins see a Resume subscription button in the billing tab's cancellation banner — one click undoes the scheduled cancel. After the period ends you'd resubscribe from the pricing page instead.
Admins delete the organization under Settings → Team → Delete organization: type its name to confirm. Download the org export first from Profile → Your data if you want a copy.
The deletion runs 7 days later. Until then the workspace works as usual, every member is emailed, the subscription stops renewing, and any admin can press Cancel deletion on the same card (renewal comes back on).
When it runs, the subscription is cancelled immediately without a refund for the rest of the period, API keys, share links, portals and Slack connections stop working, every campaign, report, file, comment and certificate is deleted, and so is every member's account, yours included. Stripe keeps your invoices. It can't be undone. Cancelling the subscription instead keeps your data, so you can come back.
FAQ
- Email: .html or .eml files, pasted HTML or message source, or a preview URL
- Copy deck: Word (.docx), Pages, or PDF — including designed PDFs; links sheets (.xlsx / .csv) via Tools → Prepare a deck
- Creative: PDF, PNG, JPG or XD (two images = desktop + mobile)
- Brand guide: PDF
- Brand voice samples: HTML pasted into the client settings
SendLint runs 100+ automated checks across nine categories: Design, Copy, Images, Links, Brand, Accessibility, Metadata, Code and Deliverability. They carry these names everywhere: a client's Checks tab, the report, the Round matrix and the exports. Each check can be individually enabled or disabled per client.
Yes. Most checks run on the HTML alone (accessibility, images, links, spam, rendering, brand compliance). The copy deck enables additional comparison checks (copy vs deck, subject line match, CTA text match, etc.). You'll see a notice that copy comparison is skipped, but all other checks will run normally.
Signed in, press Send feedback at the top of this page or under Profile → Feedback: the reply arrives on your thread there, and by email. Or email us at hello@sendlint.com with a description of the issue or feature request. Include screenshots if possible. We aim to respond within one business day (UTC-5).
Yes. Email HTML and attachments are processed in memory; saved reports persist the raw HTML and analysis output under your org account, encrypted at rest. All data is transmitted over HTTPS.
Open Profile (the avatar menu, top right) → Manage Account → Security and click Enable 2FA. Scan the QR code with any authenticator app (Google Authenticator, 1Password, Authy) — or type in the setup key manually — then enter the 6-digit code the app shows to confirm. From then on, signing in asks for a fresh code after your password. To turn it off, click Disable 2FA and confirm with a current code. If you lose access to your authenticator, email hello@sendlint.com from your account address and we'll help you recover access.