Get tech & trust data for a specific run
Changed onGet full tech & trust data for a specific historical monitoring run, including per-competitor security headers, trust signals, technology stack, robots.txt, and DNS infrastructure. Fields we could not measure are null, with a sibling availability object giving the reason; never read a null as zero, false or absent, and note that a measured 0 / false / empty list is reported as itself and is a real finding. A competitor whose robots.txt reads exists: false with NO availability marker genuinely publishes none, which allows all crawlers — a real finding, distinct from a null. A run that finished but produced no summary answers 404 run_not_summarized, which is a different fact from run_not_found: the run exists, it just has nothing to report. It used to answer 200 with an all-zero summary invented from the missing one.
Request
- Base URL: https://api.competlab.com
- URL: https://api.competlab.com/v1/projects/{projectId}/tech-trust/history/{runId}
- Auth: API key in header CL-API-Key
Path parameters
Run ID
Project ID
Response
Example response
{
"item": {
"runId": "507f1f77bcf86cd799439011",
"completedAt": "2026-03-15T10:00:00.000Z",
"summary": {
"competitorsChecked": 6,
"competitorsSuccessful": 5,
"customer": {
"domain": "yoursite.com",
"securityScore": 72,
"securitySignalsAvailable": {
"reason": "site_uses_behavioral_protection"
},
"trustSignalCount": 8,
"techStackCount": 14,
"techTrustAnalysisAvailable": {
"reason": "tech_trust_fetch_failed"
}
},
"topSecurityCompetitor": {
"domain": "rival.com",
"securityScore": 95
},
"topTrustCompetitor": {
"domain": "other.com",
"trustSignalCount": 15
},
"securityScoreGap": -23,
"trustSignalGap": -7,
"comparableCompetitors": 4
},
"competitors": [
{
"domain": "competitor.com",
"securityHeaders": {
"score": 85,
"hsts": true,
"csp": true,
"xFrameOptions": true,
"xContentTypeOptions": true,
"signalsAvailable": {
"reason": "site_uses_behavioral_protection"
}
},
"trustSignals": {
"totalCount": 10,
"categories": {
"compliance": 3,
"reviews": 4,
"socialProof": 2,
"certifications": 1,
"disclosures": 1
}
},
"technologyStack": {
"tech": [
"React",
"Next.js",
"TypeScript"
],
"growth": [
"Google Analytics",
"HubSpot"
],
"engagement": [
"Intercom",
"Zendesk"
],
"totalCount": 12,
"partialDetection": {
"reason": "site_uses_behavioral_protection"
}
},
"robotsTxt": {
"exists": true,
"totalRules": 5,
"robotsTxtAvailable": {
"reason": "access_http_error_status"
}
},
"aiAccess": {
"measurement": {
"status": "measured",
"measuredAt": "2026-08-13T04:12:00.000Z",
"couldNotMeasureReason": "access_http_error_status",
"sourcesRead": {
"robotsTxt": {
"state": "read",
"reason": "access_http_error_status",
"httpStatusCode": 200
},
"pageMetaRobotsTag": {
"state": "read",
"reason": "access_http_error_status",
"httpStatusCode": 200
},
"httpResponseHeaders": {
"state": "read",
"reason": "access_http_error_status",
"httpStatusCode": 200
}
},
"explanations": [
{
"code": "training_blocked",
"text": "Blocking a training crawler asks these operators not to use your content for model training. It does not affect whether AI assistants can cite you."
}
]
},
"assistantAccess": [
{
"assistantName": "ChatGPT",
"crawlerAccessStatus": "can_reach_site",
"appliesTo": "whole_site",
"decidedByCrawlers": [
{
"userAgentToken": "OAI-SearchBot",
"crawlerPurpose": "fetches_pages_to_cite_in_answers",
"honoursRobotsTxt": "yes",
"honoursRobotsTxtEvidence": "operator_documented",
"decidedByRuleFor": "wildcard_catch_all",
"decidedByDirective": "Disallow: /",
"decidedByLineNumber": 14
}
],
"explanations": [
{
"code": "training_blocked",
"text": "Blocking a training crawler asks these operators not to use your content for model training. It does not affect whether AI assistants can cite you."
}
]
}
],
"modelTrainingAccess": [
{
"modelOperatorName": "OpenAI",
"trainingAccessStatus": "may_use_content_for_training",
"decidedByCrawlers": [
{
"userAgentToken": "OAI-SearchBot",
"crawlerPurpose": "fetches_pages_to_cite_in_answers",
"honoursRobotsTxt": "yes",
"honoursRobotsTxtEvidence": "operator_documented",
"decidedByRuleFor": "wildcard_catch_all",
"decidedByDirective": "Disallow: /",
"decidedByLineNumber": 14
}
],
"explanations": [
{
"code": "training_blocked",
"text": "Blocking a training crawler asks these operators not to use your content for model training. It does not affect whether AI assistants can cite you."
}
]
}
],
"rulesThatMayNotWork": [
{
"userAgentInFile": "ChatGPT-User",
"directiveInFile": "Disallow: /",
"whyItMayNotWork": "operator_exempts_user_initiated_requests",
"explanation": {
"code": "training_blocked",
"text": "Blocking a training crawler asks these operators not to use your content for model training. It does not affect whether AI assistants can cite you."
}
}
],
"rulesWithUnintendedScope": [
{
"userAgentInFile": "GPTBot",
"kind": "escapes_restrictions_others_get",
"affectedRules": [
"Disallow: /use-cases/fintech",
"Disallow: /events/*"
],
"explanation": {
"code": "training_blocked",
"text": "Blocking a training crawler asks these operators not to use your content for model training. It does not affect whether AI assistants can cite you."
}
}
],
"additionalObservations": [
{
"code": "training_blocked",
"text": "Blocking a training crawler asks these operators not to use your content for model training. It does not affect whether AI assistants can cite you."
}
],
"crawlerCatalogVersion": "2026-08-13"
},
"dnsInfrastructure": {
"emailProvider": "Google Workspace",
"dnsProvider": "Cloudflare",
"emailProviderAvailable": {
"reason": "dns_lookup_failed"
},
"dnsProviderAvailable": {
"reason": "dns_lookup_failed"
}
}
}
]
}
}Changes
- breaking
the response property
//////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
///////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
////////////became optional for the status - breaking
the response property
///////////////became optional for the status - breaking
the response property
///////////////became optional for the status
- breaking
- warning
added the new
not_foundenum value to the/response property for the response status
- warning