Score domains for trust and reliability programmatically.
All API requests require a Bearer token. Get your API key from the dashboard under API Keys.
Authorization: Bearer lrn_live_abc123...https://lirnoa.com/api/v1/score?domain={domain}| Parameter | Type | Description |
|---|---|---|
domain required | string | Domain to score (e.g. example.com) |
icp_id | integer | ID of one of your ICPs (see GET /icps). When provided, fit + verdict are computed against your ICP. When omitted, the default ICP applies. |
force | boolean | Set to true to bypass cache and re-score |
timeout | integer | Timeout in ms (1000-55000). Returns 202 if scoring exceeds this limit — retry shortly for the cached result. |
referrer | string | Attribution tag (e.g. clay). Max 50 chars. |
| Header | Description |
|---|---|
X-Lirnoa-Cache | HIT or MISS |
X-Lirnoa-Latency | Processing time in ms |
X-RateLimit-Limit | Hourly rate limit |
X-RateLimit-Remaining | Requests remaining |
{
"domain": "example.com",
"score": 82,
"risk_level": "low",
"verdict": "sales_ready",
"verdict_reason": "Strong ICP match with high trust score (82/100) — route to sales.",
"verdict_components": { "trust": "high", "fit": "strong" },
"recommendation": "Route to sales — strong fit",
"confidence": 0.85,
"cached": false,
"dns": {
"domain_age_days": 10950,
"has_mx": true,
"has_spf": true,
"has_dkim": true,
"has_dmarc": true,
"ssl_valid": true,
"is_blacklisted": false
},
"web_presence": {
"has_website": true,
"has_contact_info": true,
"has_social_links": true,
"og_tags_present": true
},
"business_verification": {
"google_business_found": true,
"companies_house_found": false,
"kvk_registry_found": false,
"linkedin_found": true
},
"company": {
"name": "Example Inc.",
"industry": "Technology",
"country": "US",
"city": "San Francisco",
"employee_range": "51-200",
"domain_age_years": 30.0,
"google_rating": 4.5,
"google_review_count": 120
},
"risk_dimensions": { ... },
"quick_signals": [
{ "key": "domain_age", "label": "Domain age", "value": "30 years", "sentiment": "positive" },
{ "key": "linkedin", "label": "LinkedIn", "value": "Found — 51-200 employees", "sentiment": "positive" },
{ "key": "company_registry", "label": "Company registry", "value": "Not found", "sentiment": "neutral" },
{ "key": "google_business", "label": "Google Business", "value": "Found — 4.5★, 120 reviews", "sentiment": "positive" },
{ "key": "web_presence", "label": "Web presence", "value": "SSL valid, contact page, social links", "sentiment": "positive" },
{ "key": "third_party_mentions", "label": "Third-party mentions", "value": "Found on G2, Capterra", "sentiment": "positive" }
],
"fit": {
"score": 78,
"label": "Strong match",
"reasoning": "Matches: 50+ employees, established (3+ years)",
"icp_label": "Default ICP"
},
"analyst_assessment": {
"summary": "Example Inc. is an established technology company.",
"company_summary": "Example Inc. is an established technology company. They operate globally...",
"risk_level": "Low",
"recommendation": "Route to sales — strong fit",
"recommendation_score": 1,
"quick_signals": ["✅ Domain age: 30 years", "✅ LinkedIn found"]
},
"scored_at": "2026-03-18T12:00:00.000Z",
"latency_ms": 8500
}The verdict field is the actionable triage decision for an inbound signup. One of:
flag — high fraud or low-trust risk; recommend blocking or manual review.review — ambiguous signals; worth a quick human look.self_serve — legitimate company but unlikely high-value account; let them use the product organically.sales_ready — matches ICP signals AND high trust; route to sales for proactive outreach.verdict_components exposes the two ingredients (trust: high/medium/low, fit: strong/possible/poor) so consumers can filter beyond the headline. verdict_reason is a short deterministic sentence explaining the verdict.
Standalone calls (no fit_criteria) are evaluated against a default ICP (50+ employees AND established / recently funded / actively hiring). The fit.icp_label field reads "Default ICP" in this case.
The top-level quick_signals array returns up to 8 typed signals: domain_age, linkedin, company_registry, google_business, web_presence, third_party_mentions, plus hiring_signals and tech_stack when commercial-activity scoring runs. Each entry has { key, label, value, sentiment } with sentiment in positive | negative | neutral | warning.
The legacy analyst_assessment.quick_signals array (free-form emoji-prefixed strings) is preserved for backward compatibility but is deprecated. Prefer the structured top-level field.
When using the timeout parameter and scoring takes longer than the specified limit:
{
"status": "scoring",
"domain": "newdomain.com",
"message": "Domain is being scored. Retry shortly.",
"retry_after_seconds": 30
}/icpsReturns the active ICPs in your workspace. Use any returned id as the icp_id query param when calling /score.
{
"icps": [
{
"id": 12,
"name": "Series B SaaS",
"raw_criteria": "B2B SaaS, 50-200 employees, US or UK, sales-led motion",
"interpretation": "Targeting growth-stage B2B SaaS in US/UK with active outbound motion.",
"created_at": "2026-04-12T09:30:00.000Z",
"updated_at": "2026-04-25T14:10:00.000Z"
}
]
}Pass icp_id to score a domain against your ICP instead of the default. The response's fit.icp_label will reflect the ICP name; verdict, verdict_components, and the analyst's Sales Potential paragraph are all computed against the ICP's criteria.
curl -H "Authorization: Bearer lrn_live_YOUR_KEY" \
"https://lirnoa.com/api/v1/score?domain=example.com&icp_id=12"Errors: 400 INVALID_ICP_ID if icp_id isn't a number; 404 ICP_NOT_FOUND if the ID doesn't belong to your workspace.
curl -H "Authorization: Bearer lrn_live_YOUR_KEY" \
"https://lirnoa.com/api/v1/score?domain=example.com"const res = await fetch(
'https://lirnoa.com/api/v1/score?domain=example.com',
{ headers: { Authorization: 'Bearer lrn_live_YOUR_KEY' } }
);
const data = await res.json();
console.log(data.score, data.risk_level);import requests
res = requests.get(
'https://lirnoa.com/api/v1/score',
params={'domain': 'example.com'},
headers={'Authorization': 'Bearer lrn_live_YOUR_KEY'}
)
data = res.json()
print(data['score'], data['risk_level'])| Plan | Per Second | Per Hour | Monthly Credits |
|---|---|---|---|
| Free ($0/mo) | 1 | 60 | 25 |
| Starter ($29/mo) | 3 | 180 | 200 |
| Pro ($79/mo) | 5 | 300 | 750 |
Rate-limited requests return 429 Too Many Requests with a Retry-After header. Quota-exceeded requests return 402 Payment Required.
{
"error": {
"code": "INVALID_DOMAIN",
"message": "The provided domain is not valid."
}
}| Code | HTTP | Meaning |
|---|---|---|
MISSING_DOMAIN | 400 | No domain parameter provided |
INVALID_DOMAIN | 400 | Domain could not be parsed |
UNAUTHORIZED | 401 | Missing or invalid API key |
RATE_LIMITED | 429 | Rate limit exceeded |
QUOTA_EXCEEDED | 402 | Monthly quota exceeded |
INTERNAL_ERROR | 500 | Server error |