Site Decay
For partners

Site Decay API

Structured website check-ups for your tools. Every finding comes from a live check, with the evidence behind it. Machine-readable: OpenAPI spec · issue codes (JSON).

Get a key

Keys are issued per partner after a quick review by a person. Request one below, or programmatically: POST /api/v1/access-request with {"name", "email", "use_case", "organization", "website", "expected_volume", "is_agent"}. If approved, a one-time link to your key is emailed to you.

Authentication

Send your key on every request: Authorization: Bearer sd_… (or X-API-Key: sd_…). Keys are issued per partner through a one-time link.

curl -H "Authorization: Bearer YOUR_KEY" "https://sitedecay.com/api/v1/check?domain=example.com"

Endpoints

GET /api/v1/check?domain=Latest result if a check-up ran in the last 24 hours (cached: true), otherwise runs one now, about 15 seconds. &fresh=1 forces a new one; &wait=0 queues it and returns 202 with a batch_id.
POST /api/v1/check/batchBody {"domains": [...], "fresh": false}, up to 100. Returns 202 with batch_id, status_url, already_fresh, queued, invalid, estimated_minutes.
GET /api/v1/batch/{batch_id}total, done, complete, pending[], failed[] and results[] (each a result as below). Domains are checked one at a time, about 4 a minute: poll every 30–60 seconds.

A result

domainThe domain checked
report_urlPublic report with screenshots, safe to share with the site owner
overall_statuscritical (any critical issue) · needs_attention (any high or medium) · healthy (low/info only) · not_checkable
checked_atWhen the check-up ran, ISO 8601 UTC
issue_count, countsTotal, and per severity: critical high medium low info
summaryThe top finding in plain English when it's medium or worse, else null
platformDetected builder or CMS (WordPress, Wix, Squarespace…)
mobilePhone measurements from a 390px-wide render: built_for_phones, has_viewport, viewport, zoom_disabled, layout_width (390 fits, ~980 is a shrunken desktop page), page_width, horizontal_scroll, small_text_share, tap_targets, small_tap_targets, phone_tappable. Null on check-ups from before Oct 2026.
cachedSingle check only: served from a check-up under 24 hours old
issues[]Most severe first. Each: code, severity, label (which check), finding (plain English), fix (or null), evidence[] (the exact observations: hosts, errors, dates)
{
  "domain": "expired.badssl.com",
  "report_url": "https://sitedecay.com/check/expired.badssl.com?ref=api-yourname",
  "overall_status": "critical",
  "checked_at": "2026-10-08T02:31:46+00:00",
  "issue_count": 5,
  "counts": {"critical": 1, "high": 0, "medium": 2, "low": 2, "info": 0},
  "summary": "Anyone who opens https://expired.badssl.com is blocked by a full-page “Not Secure” warning: its certificate expired on Apr 12, 2015.",
  "platform": "Custom or unknown",
  "cached": false,
  "issues": [
    {"code": "SSL_BLOCKED", "severity": "critical", "label": "Security certificate",
     "finding": "Anyone who opens https://expired.badssl.com is blocked by a full-page “Not Secure” warning: its certificate expired on Apr 12, 2015.",
     "fix": "Your host can install a free certificate (Let's Encrypt) that renews itself.",
     "evidence": ["https://expired.badssl.com: certificate has expired; certificate dated to Apr 12, 2015; issued for *.badssl.com, badssl.com"]},
    {"code": "NO_EMAIL_SETUP", "severity": "medium", "label": "Email for your domain",
     "finding": "This domain isn't set up to receive email.", "fix": "If you use email at this domain, its mail records need fixing.", "evidence": []},
    {"code": "NO_TAP_TO_CALL", "severity": "low", "label": "Tap-to-call phone link",
     "finding": "No: phone visitors can’t tap to call", "fix": null, "evidence": []}
  ]
}

Issue codes

Stable identifiers: new codes may be added, existing ones won't change meaning.

CodeSeverityMeaning
SITE_DOWNcriticalThe homepage doesn't load (checked over https and http).
SSL_BLOCKEDcriticalBrowsers block the site with a full-page certificate warning.
HIDDEN_SPAM_LINKScriticalHidden links to gambling/spam sites were planted in the page code (a hack).
SPAM_CONTENTcriticalThe page shows injected gambling or pharmacy spam (a hack).
SITE_ERROR_PAGEcriticalThe site shows a database or server error instead of its pages.
SITE_PARKED_OR_SUSPENDEDcriticalThe address shows a parked, for-sale or suspended page.
SSL_EXPIRING_SOONhighThe certificate expires within about two weeks.
INSECURE_FORMhighA contact/appointment form sends what people type without encryption.
NOT_MOBILE_FRIENDLYhighNo phone layout: phones show a shrunken desktop page (confirmed by rendering).
OUTDATED_WORDPRESShighWordPress is well behind the current release (medium when only slightly behind).
BLOCKS_SEARCH_ENGINEShighThe homepage tells search engines not to list it (noindex).
DOMAIN_EXPIRINGhighThe domain registration expires soon.
SSL_CHAIN_INCOMPLETEmediumThe certificate is missing its intermediate: Chrome copes, Firefox and many phones don't.
SSL_ONE_ADDRESS_BROKENmediumhttps works with or without www, but not both.
INSECURE_FILESmediumThe secure page loads some files over plain http (mixed content).
NO_HTTPS_REDIRECTmediumThe site opens over plain http and doesn't send visitors to https.
REDIRECTS_ELSEWHEREmediumThe address lands on a different website.
NO_EMAIL_SETUPmediumThe domain isn't set up to receive email (no working MX).
MAINTAINER_GONEmediumThe web designer credited on the site is no longer in business.
WWW_ADDRESS_ISSUEmediumThe www. version of the address is broken or goes somewhere else.
MISSING_VIEWPORTmediumNo viewport tag, so phones zoom out to a desktop-width page (comes with NOT_MOBILE_FRIENDLY).
HORIZONTAL_SCROLLmediumHas a phone layout, but parts of the page are wider than the screen (sideways scrolling).
SMALL_TEXTmediumHas a phone layout, but 30%+ of the text is under 12px.
SMALL_TAP_TARGETSmediumHas a phone layout, but many links/buttons are under 24x24px (WCAG 2.2 minimum).
SEPARATE_MOBILE_SITElowPhones get a separate, older-style mobile site.
ZOOM_DISABLEDlowThe viewport turns off pinch-to-zoom (user-scalable=no or maximum-scale=1).
MISSING_META_DESCRIPTIONlowNo description for Google to show under the title.
WEAK_PAGE_TITLElowThe homepage title is generic or missing.
STALE_FOOTER_YEARlowThe footer copyright year is several years old.
NO_TAP_TO_CALLlowNo tap-to-call phone link for phone visitors.
NO_COMPRESSIONlowPages are sent uncompressed.
SLOW_SERVERlowThe server takes over two seconds to answer.
HEAVY_HOMEPAGElowThe homepage's code is over 400 KB.
MANY_FILESlowThe homepage loads a very large number of files.
HEADING_ISSUElowThe page's main heading (H1) is missing or repeated.
MISSING_ALT_TEXTlowMany images have no description (alt text).
NO_BUSINESS_SCHEMAlowNo structured business details for Google (schema.org).
HSTS_OFFinfoBrowsers aren't told to always use https (HSTS).
NO_SOCIAL_PREVIEWinfoLinks shared on social media show no preview card.
NO_FAVICONinfoNo browser tab icon.
HTTP_NOT_ANSWERINGinfoPlain http:// doesn't answer (browsers use https anyway).
CHECK_BLOCKEDinfoThe site turned the check away (401/403/429), so it couldn't be read like a visitor would.
CONTENT_NOT_CHECKEDinfoA security screen stopped the content check; other checks still ran.

Limits and errors

Each key has a daily limit of new check-ups (cached reads don't count). Errors are JSON {"error": "…"} with 400 (bad domain or body), 401 (missing or unknown key), 404 (unknown batch), 429 (daily limit).