Trust Signals
REST endpoints for Trust Signals. Base URL https://api.competlab.com; every request needs a CL-API-Key header (see Authentication). Responses wrap in { item } or { items }; errors in { error }.
Start an async trust-signals scan
/v1/tools/trust-signals/scansStart an asynchronous trust-signal analysis for a public domain. Returns a tier verdict (comprehensive / substantial / moderate / minimal) with a 0-100 score and a per-category breakdown across five buyer-concern areas: enterprise readiness, third-party validation, social proof, brand authority, and risk reversal. Also surfaces suspicious patterns (e.g. unverified compliance claims, count-vs-logo mismatches, unlinked press mentions) and gaps versus tier benchmarks. Returns sub-second with item: { id, status: "queued", createdAt, expiresAt } — poll GET /v1/tools/trust-signals/scans/{scanId} until status is completed or failed. Most scans complete in seconds; heavy-render sites can take up to ~90 seconds. Result and error payloads are persisted for 24h, after which the scan auto-deletes and GET returns 404. No project required. Suitable for sales discovery, due-diligence flows, and competitive credibility audits — and the only supported shape for MCP clients (Cursor / Claude Desktop hardcode 60-second tool-call timeouts).
Request body — application/json
| Field | Type | Description |
|---|---|---|
domain | string | Target domain to scan for trust signals. Accepts a bare hostname or a full URL — normalized (lowercased, scheme and path stripped) before scanning. |
Request
curl -X POST "https://api.competlab.com/v1/tools/trust-signals/scans" \
-H "CL-API-Key: YOUR_COMPETLAB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domain":"stripe.com"}'Response 200 OK
Example
{
"item": {
"id": "6638e9a1b2c3d4e5f6a7b8c9",
"status": "queued",
"createdAt": "2026-05-17T14:30:00.000Z",
"expiresAt": "2026-05-18T14:30:00.000Z"
}
}Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_parameters | Bad request — the payload failed validation. |
| 401 | api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scope | The CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope. |
| 429 | rate_limit_exceeded | Rate limit exceeded — retry with backoff. |
| 502 | bad_gateway | Upstream fetch failed (e.g. the target page could not be retrieved). |
Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.
{
"error": {
"code": "invalid_parameters",
"message": "Domain is required",
"status": 400
}
}Transient failures (429, 5xx) are safe to retry with exponential backoff.
Get an async trust-signals scan by ID
/v1/tools/trust-signals/scans/{scanId}Get the current state of an async trust-signals scan. Returns the scan’s lifecycle (queued / running / completed / failed) along with createdAt and expiresAt always, plus startedAt once the runner picks it up and completedAt once it reaches a terminal state. On completed the full canonical scan response is in item.result (tier verdict, category scores, detected signals with evidence, suspicious patterns, gaps). On failed the failure details are in item.error with a machine-readable code — currently homepage_fetch_failed (upstream homepage fetch threw) or scan_failed (any other error during scan execution). Scoped to the API key’s organization — cross-tenant access, never-existed IDs, expired IDs (24h TTL), and malformed IDs all return 404 scan_not_found with an identical envelope to prevent existence-disclosure. Typically sub-second — safe to poll on a 2–5 second interval depending on your timeout budget.
Path parameters
| Name | Type | Description |
|---|---|---|
scanId | string |
Request
curl "https://api.competlab.com/v1/tools/trust-signals/scans/65a1b2c3d4e5f6a7b8c9d0e1" \
-H "CL-API-Key: YOUR_COMPETLAB_API_KEY"Response 200 OK
Example
{
"item": {
"id": "6638e9a1b2c3d4e5f6a7b8c9",
"status": "completed",
"createdAt": "2026-05-17T14:30:00.000Z",
"expiresAt": "2026-05-18T14:30:00.000Z",
"startedAt": "2026-05-17T14:30:00.412Z",
"completedAt": "2026-05-17T14:30:02.840Z",
"result": {
"domain": "stripe.com",
"finalUrl": "https://stripe.com/",
"fetchedAt": "2026-05-17T14:30:02.000Z",
"verdict": {
"tier": "substantial",
"score": 38,
"benchmarkForTier": 34,
"benchmarkComparison": "above-average",
"summary": "Substantial trust coverage — strong social proof and some compliance signals, above-average for tier"
},
"categoryScores": {
"enterpriseReadiness": {
"score": 8,
"max": 25,
"signalsFound": 1
},
"thirdPartyValidation": {
"score": 12,
"max": 20,
"signalsFound": 3
},
"socialProof": {
"score": 10,
"max": 20,
"signalsFound": 2
},
"brandAuthority": {
"score": 5,
"max": 20,
"signalsFound": 1
},
"riskReversal": {
"score": 3,
"max": 15,
"signalsFound": 1
}
},
"signalsDetected": [
{
"signal": "SOC 2",
"category": "enterpriseReadiness",
"weight": 8,
"confidence": "high",
"evidenceCount": 1,
"evidence": [
{
"kind": "html",
"source": "soc 2",
"matched": "SOC 2 Type II compliant"
}
]
}
],
"suspiciousPatterns": [],
"gapsVsBenchmark": [
{
"signal": "Customer logos",
"category": "socialProof",
"benchmarkPrevalence": "87% of substantial-tier peers have this",
"ciInsight": "Add customer logos to homepage — table stakes for substantial-tier SaaS positioning"
}
],
"meta": {
"signalsEvaluated": 34,
"benchmarkSource": "CompetLab SaaS Trust Benchmarks 2026-Q2 (n=247)",
"scanDurationMs": 2840
}
}
}
}Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scope | The CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope. |
| 404 | scan_not_found | No scan matches the id in the path. |
| 429 | rate_limit_exceeded | Rate limit exceeded — retry with backoff. |
Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.
{
"error": {
"code": "api_key_invalid",
"message": "Invalid API key",
"status": 401
}
}Transient failures (429, 5xx) are safe to retry with exponential backoff.