External developer API

Developer API docs for authenticity verdicts and score advisory

Add MyDomainRisk authenticity verdicts and security score advisory statements to your own onboarding, domain review or fraud-prevention workflow. External developer keys are separate from account API keys and can only access the developer authenticity verdict and security score advisory endpoints.

Base URL

https://api.mydomainrisk.com/api/developer/v1

Create a developer key

Overview

The external developer API is intentionally separate from the paid-user account API. It gives approved developers API-key protected access to domain authenticity verdicts and security score advisory statements.

External developer keys do not work on the paid-user /api/v1 account API and do not return tracked-domain history, signed-in reports, scan ownership IDs or paid evidence packs.

Two kinds of check

MyDomainRisk runs two different depths of check, and this API gives you the shallower one. The difference is not a limit on how many you may run — it is a difference in how much analysis is done and how much detail comes back.

Quick check (this API)A score or a verdict, and the titles of what was found. The same check, the same depth and the same detail a visitor gets on our website — nothing more and nothing less.
Full scan (signed in)A deeper analysis with the detailed findings, the recommended actions, the report and the history. Available in the app, and over the account API for the account's own domains.

What the quick check does not do

  • It does not explain a finding. You get a title and a severity, not the analysis behind it, the remediation steps, or which sources contributed.
  • Its score is a floor. It reads a lighter exposure index, so a full scan can return the same score or a higher one, never a lower one. When that applies, coverage_note says so in the response — do not present the number without it.
  • It may report a provisional authenticity verdict. When enrichment_status is pending, two slower signals are still running and the verdict may still change. Nothing is pushed to you when they finish. Request the same domain again shortly and you will be served the enriched answer, which reports completed. A not_applicable verdict needed no slow signal and will not change however often you ask. This is exactly how the website behaves — a visitor is not notified either.
  • It may not have read the homepage. homepage.reviewed tells you whether it did, and homepage.blocked_by names what stopped it. “Nothing found” and “the page could not be fetched” are different answers and must not be shown the same way.
  • Results are cached for up to 20 minutes and there is no force-refresh. A domain that changed in the last few minutes may not show it yet.

Because it is the same check a visitor can run, it carries the same allowance: five per hour. It does not consume the account's daily check allowance, which belongs to full scans.

These are outcome-level answers for vetting and triage. They are not a substitute for a full scan of a domain you are responsible for.

Machine-readable contract

The full API contract is published as an OpenAPI 3.1 document. Validate responses in your CI or generate typed clients from it rather than transcribing the tables below.

curl -sS https://mydomainrisk.com/openapi.json

The same document is reachable from the API host, which redirects to the address above:

curl -sSL https://api.mydomainrisk.com/api/developer/v1/openapi.json

It carries the exact permitted values for every field with a fixed set of answers — verdicts, grades, score buckets and finding severities — so nothing on this page needs to be inferred from example responses.

Authentication

Developer API keys are available on every plan, including Free. A key carries its owner's account and can do what that account can do — no more. Create a Developer API - authenticity and score advisory key from the account area and send it as a Bearer token.

Authorization: Bearer mdr_live_<id>_<secret>

Use developer keys only from server-side code. Do not put them in browser JavaScript, mobile apps, public repositories or client-side logs.

Validate a key before building against it:

GET https://api.mydomainrisk.com/api/developer/v1/me
Authorization: Bearer mdr_live_<id>_<secret>

{
  "api": "developer",
  "version": "v1",
  "scope": "developer_peek",
  "tier": "pro",
  "capabilities": [
    { "operation_id": "getDeveloperCapabilities", "method": "GET", "path": "/me" },
    { "operation_id": "checkDomainSecurity", "method": "GET", "path": "/peek/security" },
    { "operation_id": "checkDomainAuthenticity", "method": "GET", "path": "/peek/authenticity" }
  ],
  "limits": {
    "requests_per_minute_per_key": 120,
    "requests_per_minute_per_ip": 60,
    "requests_per_hour_per_subnet": 150,
    "cache_max_age_seconds": 1200
  },
  "entitlements": {
    "security_score_advisory": true,
    "authenticity_verdict": true,
    "account_data": false,
    "force_refresh": false,
    "consumes_account_daily_allowance": false
  }
}

The capability response deliberately contains no account email or customer data.

If you need API access and do not have an account, or want to discuss a partner arrangement, contact support@mydomainrisk.com.

Security score advisory

GET https://api.mydomainrisk.com/api/developer/v1/peek/security?domain=example.com
Authorization: Bearer mdr_live_<id>_<secret>

Example response:

{
  "domain": "example.com",
  "checked_at": "2026-08-17T12:00:00Z",
  "score": 82,
  "grade": "B",
  "score_summary": {
    "bucket": "good",
    "label": "Good"
  },
  "findings": [
    {
      "title": "DMARC policy could be stronger",
      "severity": "medium"
    }
  ],
  "total_findings": 1,
  "cache": { "hit": false, "max_age_seconds": 1200 },
  "scan_time_ms": 842
}

Authenticity verdict

GET https://api.mydomainrisk.com/api/developer/v1/peek/authenticity?domain=example.com
Authorization: Bearer mdr_live_<id>_<secret>

You can include optional brand context when the expected organisation name is known:

GET https://api.mydomainrisk.com/api/developer/v1/peek/authenticity?domain=example.com&expected_brand=Example%20Ltd
Authorization: Bearer mdr_live_<id>_<secret>

Example response:

{
  "domain": "example.com",
  "checked_at": "2026-08-17T12:00:00Z",
  "verdict": "genuine",
  "findings": [],
  "total_findings": 0,
  "factual": {
    "resolves": true,
    "registrar": "Example Registrar Ltd",
    "age_days": 10950,
    "has_tls": true
  },
  "cache": { "hit": false, "max_age_seconds": 1200 },
  "scan_time_ms": 936
}

Authenticity verdict values:

genuineNo material authenticity concern visible. Map to pass / green.
probablyLegitLikely legitimate with minor caveats. Map to pass / green.
uncertainCannot confidently classify. A human should review. Map to review / amber.
suspiciousConcerning signals present. Treat with caution. Map to review or fail / amber-red.
maliciousStrong malicious or impersonation signals. Do not treat as safe. Map to fail / red.

For simple traffic-light integrations, map genuine and probablyLegit to pass, uncertain and suspicious to review, and malicious to fail.

Fields

Security score advisory fields

domainThe normalised domain submitted for checking.
checked_atISO 8601 check time. May be null for a cached result created before this field was introduced.
scoreSecurity score advisory on a 0–100 scale. Higher is better — 0 is the worst result, 100 the best.
gradeDisplay grade derived from the score. One of: A, B, C, D, F. Presentation text — branch on score_summary.bucket instead.
score_summaryObject with bucket and label. bucket is one of: strong, goodWithGaps, needsImprovement, atRisk, critical — listed here worst to best in reverse. label is the plain-English wording for the same bucket, and is display text only.
findingsArray of current public findings. Each item contains title and severity only. severity is one of: critical, high, medium, low, info.
total_findingsCount of current public findings.
cacheObject containing hit and max_age_seconds.
scan_time_msRuntime for the request in milliseconds.

Branch on score_summary.bucket rather than comparing score against your own thresholds. The bucket is part of the contract; a threshold you pick yourself is not, and will drift from ours without any error to tell you.

Authenticity verdict fields

domainThe normalised domain or URL host submitted for checking.
checked_atISO 8601 check time. May be null for a cached result created before this field was introduced.
verdictOne of: genuine, probablyLegit, uncertain, suspicious, malicious — listed best to worst. No other value is ever returned. probablyLegit is a POSITIVE verdict; treating it as a failure or an unknown is the most common integration mistake.
findingsArray of current public findings. Each item contains title and severity only.
total_findingsCount of current public findings.
factualStrict factual context: resolves, age_days, has_tls and registrar; unavailable age or registrar values are null.
cacheObject containing hit and max_age_seconds.
scan_time_msRuntime for the request in milliseconds.

Results are cached for up to 20 minutes. There is no force-refresh option on the developer API; present results as a recent advisory rather than a permanent decision for domains that may have just changed.

Limits and errors

Developer API requests are limited to 120 requests per minute per key, 60 per minute per IP and 150 per hour per subnet.

The allowance that actually binds a check is five per hour, per IP — the same allowance a visitor gets running the same check on our website. The per-minute figures above are burst guards sitting on top of it. /me reports it as peeks_per_hour_per_ip, and reading /me does not count against it.

These checks do not consume the account's daily check allowance. That allowance belongs to full scans, which are deeper and are a different thing entirely.

400/422Invalid request body, query string or malformed domain.
401Missing, malformed, unknown or revoked API key.
403Wrong key type, or account not eligible for API access.
429Rate limit or platform guard reached.
503Temporary queue, cache or quota-store issue. Retry later.
504The upstream check did not finish in time. Retry later.

Every failure returns the same JSON shape, on every path and at every status. Branch on error.code, not on the message text:

{ "error": { "code": "rate_limited", "message": "...", "retry_after_seconds": 30 } }
invalid_api_key401. Missing, malformed, unknown or revoked key.
forbidden403. Wrong key type, or the account is not eligible.
invalid_domain422. The domain or URL host could not be parsed.
rate_limited429. An allowance was reached — the hourly check allowance or a burst guard. Honour Retry-After, or error.retry_after_seconds.
temporarily_unavailable503. A transient queue, cache or quota-store issue.
scan_timeout504. The upstream check did not finish in time.
request_failedAny status. The fallback when no more specific code applies.

Treat this list as the codes worth handling individually, not as a closed set: recognise these and fall back on the HTTP status for anything else, so a new code never breaks your integration.

A 429 carries a Retry-After header as well as the field above. Back off on it rather than on a fixed interval.

Acceptable use

The API is for legitimate business, security, fraud-prevention, customer-protection and compliance workflows. MyDomainRisk performs non-intrusive external analysis only.

Allowed

  • Onboarding and signup checks.
  • Customer, partner and domain review.
  • Internal fraud, risk and security workflows.

Not allowed

  • Exploitation, attack simulation or credential testing.
  • Bypassing quotas, cooldowns or access controls.
  • Using paid-user account keys as external developer keys.

Privacy and data handling

The developer API receives the domain and request metadata needed to provide the service, authenticate the caller, enforce limits and protect the platform. MyDomainRisk does not sell API submission data.

Developer API results may be cached and counted in aggregate telemetry according to the same public domain-check operating model and the MyDomainRisk privacy policy. For privacy questions, contact support@mydomainrisk.com.

Changelog

2026-06-25

Public developer docs updated with key validation, example JSON responses, verdict values, rate limits, and cache guidance for the separate external developer API.