Intelligence Token JSON Reference
Intelligence Token JSON Reference
Quick answer: Intelligence Tokens return structured JSON data via https://api.surmado.com/intelligence/{TOKEN}. Signal tokens include presence_rate (0-1), authority_score (0-100), ghost_influence (0-1), competitors array, platform variance. Scan tokens include overall_score (0-100), category scores, issues array, Core Web Vitals per page/browser. Solutions tokens include recommendations array, model perspectives, risk assessment. All numeric values (not percentages) for easy computation. No authentication required.
Reading time: 22 minutes
In this guide:
- Signal JSON returns decimals not percentages where presence_rate: 0.42 means 42% (multiply by 100 for display), authority_score: 78 is already 0-100 scale (use directly), ghost_influence: 0.28 means 28% (multiply by 100), enabling computation (0.42 - 0.54 = -0.12 competitive gap) without string parsing
- Access 8 platform-specific metrics via platform_variance.chatgpt.presence_rate (0.52), platform_variance.claude.presence_rate (0.38), etc. for all platforms (ChatGPT/Claude/Gemini/DeepSeek/Meta AI/Grok/ChatGPT Search/Perplexity) with sample_size: 7 per platform, identifying optimization targets by finding lowest rates
- Scan JSON includes per-page Core Web Vitals with lcp.median: 2.8 seconds (target < 2.5), cls.median: 0.08 (target < 0.1), inp.median: 180ms (target < 200), status: “needs_improvement”/“good”/“poor”, plus issues array sorted by severity (“high”/“medium”/“low”) with page location and actionable recommendations
- Solutions JSON provides adversarial recommendations with recommendations array (priority: 1-N, action, rationale, estimated_impact, estimated_cost, risk level), model_perspectives object (cfo/coo/market_realist/game_theorist/chief_strategist/wildcard views with confidence levels), and risk_assessment with key_risks + mitigation_strategies arrays for implementation planning
- Implement common integration patterns including quarterly tracking (fetch 4 tokens → pandas DataFrame showing 28% → 48% growth), platform optimization (find weakest.rate from platform_variance), competitive alerts (calculate your_rank from competitors array → Slack if rank > 3), Scan prioritization (filter issues by severity==“high”), Solutions risk dashboard (filter recommendations by acceptable risk)
API Endpoint: https://api.surmado.com/intelligence/{TOKEN}
Signal Token JSON Schema
Top-Level Structure
Example response for SIG-2025-11-A1B2C:
{
"product": "signal",
"token": "SIG-2025-11-A1B2C",
"created_at": "2025-11-10T14:23:11Z",
"business": {
"name": "Phoenix Cool Air",
"industry": "HVAC",
"location": "Phoenix, AZ"
},
"test_parameters": {
"personas_tested": 5,
"total_queries": 56,
"ai_platforms": 8
},
"metrics": {
"presence_rate": 0.42,
"authority_score": 78,
"ghost_influence": 0.28,
"category_share": 0.046
},
"competitors": [
{
"name": "Competitor A",
"presence_rate": 0.54,
"authority_score": 82,
"rank": 1
},
{
"name": "Competitor B",
"presence_rate": 0.38,
"authority_score": 71,
"rank": 3
}
],
"platform_variance": {
"chatgpt": {
"presence_rate": 0.52,
"authority_score": 81,
"sample_size": 7
},
"claude": {
"presence_rate": 0.38,
"authority_score": 74,
"sample_size": 7
},
"gemini": {
"presence_rate": 0.41,
"authority_score": 76,
"sample_size": 7
},
"deepseek": {
"presence_rate": 0.35,
"authority_score": 72,
"sample_size": 7
},
"meta_ai": {
"presence_rate": 0.44,
"authority_score": 79,
"sample_size": 7
},
"grok": {
"presence_rate": 0.39,
"authority_score": 75,
"sample_size": 7
},
"chatgpt_search": {
"presence_rate": 0.48,
"authority_score": 80,
"sample_size": 7
},
"perplexity": {
"presence_rate": 0.56,
"authority_score": 83,
"sample_size": 7
}
},
"tier": "pro"
}
Field Reference: Signal Tokens
product
- Type: String
- Value: Always
"signal"for Signal tokens - Use case: Identify token type programmatically
token
- Type: String
- Format:
SIG-YYYY-MM-XXXXX - Example:
"SIG-2025-11-A1B2C" - Use case: Token identifier for tracking
created_at
- Type: ISO 8601 datetime string
- Format:
YYYY-MM-DDTHH:MM:SSZ(UTC) - Example:
"2025-11-10T14:23:11Z" - Use case: Timestamp for historical tracking
business.name
- Type: String
- Example:
"Phoenix Cool Air" - Use case: Business identification
business.industry
- Type: String
- Example:
"HVAC","Moving","Legal Services" - Use case: Industry categorization
business.location
- Type: String
- Example:
"Phoenix, AZ","Dallas/Fort Worth, TX" - Use case: Geographic context
test_parameters.personas_tested
- Type: Integer
- Range: 3-15 (typically 5-7)
- Example:
5 - Use case: Understanding test scope
test_parameters.total_queries
- Type: Integer
- Value: Always
56(8 queries × 7 AI platforms) - Use case: Sample size reference
test_parameters.ai_platforms
- Type: Integer
- Value: Always
7 - Use case: Platform coverage reference
metrics.presence_rate
- Type: Float
- Range:
0.0to1.0 - Format: Decimal (not percentage)
- Example:
0.42= 42% - Use case: Core visibility metric
- Calculation:
presence_rate * 100for percentage display
metrics.authority_score
- Type: Integer
- Range:
0to100 - Example:
78 - Null case:
nullifpresence_rate == 0(no mentions to analyze) - Use case: Positioning quality metric
metrics.ghost_influence
- Type: Float
- Range:
0.0to1.0 - Format: Decimal (not percentage)
- Example:
0.28= 28% - Use case: Attribution gap measurement
metrics.category_share
- Type: Float
- Range:
0.0to1.0 - Format: Decimal (not percentage)
- Example:
0.046= 4.6% - Use case: Market share of mentions
competitors[].name
- Type: String
- Example:
"Competitor A" - Use case: Competitive identification
competitors[].presence_rate
- Type: Float
- Range:
0.0to1.0 - Example:
0.54= 54% - Use case: Competitive benchmarking
competitors[].authority_score
- Type: Integer
- Range:
0to100 - Example:
82 - Null case:
nullif competitor has 0% presence rate - Use case: Competitive positioning comparison
competitors[].rank
- Type: Integer
- Range:
1toN(total competitors) - Example:
1(highest presence rate) - Use case: Competitive ranking
platform_variance.{platform}.presence_rate
- Type: Float
- Range:
0.0to1.0 - Platforms:
chatgpt,claude,gemini,deepseek,meta_ai,grok,chatgpt_search,perplexity - Example:
0.52= 52% on ChatGPT - Use case: Platform-specific optimization
platform_variance.{platform}.authority_score
- Type: Integer
- Range:
0to100 - Null case:
nullif platform-specific presence rate is 0 - Use case: Platform-specific positioning analysis
platform_variance.{platform}.sample_size
- Type: Integer
- Value: Always
7(7 queries per platform) - Use case: Statistical confidence reference
tier
- Type: String
- Values:
"essential"or"pro" - Use case: Report tier identification
Scan Token JSON Schema
Top-Level Structure
Example response for SCAN-2025-11-D4E5F:
{
"product": "scan",
"token": "SCAN-2025-11-D4E5F",
"created_at": "2025-11-10T15:42:33Z",
"website": {
"url": "https://phoenixcoolair.com",
"pages_tested": 30
},
"overall_score": 68,
"category_scores": {
"technical_seo": 72,
"performance": 58,
"accessibility": 64,
"security": 81
},
"core_web_vitals": {
"lcp": {
"median": 2.8,
"p75": 3.2,
"status": "needs_improvement"
},
"cls": {
"median": 0.08,
"p75": 0.12,
"status": "good"
},
"inp": {
"median": 180,
"p75": 220,
"status": "good"
}
},
"issues": [
{
"type": "performance",
"severity": "high",
"page": "/services",
"issue": "LCP exceeds 4.0s on mobile",
"recommendation": "Optimize hero image (currently 2.3MB uncompressed)",
"impact": "SEO ranking, user experience"
},
{
"type": "accessibility",
"severity": "medium",
"page": "/contact",
"issue": "Form inputs missing labels",
"recommendation": "Add <label> elements to all form inputs",
"impact": "WCAG compliance, screen reader accessibility"
}
],
"browsers_tested": [
"chrome_desktop",
"firefox_desktop",
"safari_macos",
"safari_ios",
"edge_desktop",
"chrome_android",
"brave_desktop",
"instagram_inapp",
"facebook_inapp"
],
"tier": "pro"
}
Field Reference: Scan Tokens
product
- Type: String
- Value: Always
"scan"for Scan tokens
token
- Type: String
- Format:
SCAN-YYYY-MM-XXXXX - Example:
"SCAN-2025-11-D4E5F"
created_at
- Type: ISO 8601 datetime string
- Example:
"2025-11-10T15:42:33Z"
website.url
- Type: String (URL)
- Example:
"https://phoenixcoolair.com" - Use case: Website identification
website.pages_tested
- Type: Integer
- Range: Up to 30 (Essential) or 100 (Pro)
- Example:
30 - Use case: Test scope reference
overall_score
- Type: Integer
- Range:
0to100 - Example:
68 - Use case: Overall site health metric
category_scores.technical_seo
- Type: Integer
- Range:
0to100 - Example:
72 - Use case: SEO health metric
category_scores.performance
- Type: Integer
- Range:
0to100 - Example:
58 - Use case: Speed/performance metric
category_scores.accessibility
- Type: Integer
- Range:
0to100 - Example:
64 - Use case: WCAG compliance metric
category_scores.security
- Type: Integer
- Range:
0to100 - Example:
81 - Use case: Security health metric
core_web_vitals.lcp.median
- Type: Float
- Unit: Seconds
- Example:
2.8(2.8 seconds) - Target:
< 2.5(good),2.5-4.0(needs improvement),> 4.0(poor)
core_web_vitals.lcp.p75
- Type: Float
- Unit: Seconds
- Example:
3.2 - Use case: 75th percentile (Google’s scoring metric)
core_web_vitals.lcp.status
- Type: String
- Values:
"good","needs_improvement","poor" - Use case: Quick status check
core_web_vitals.cls.median
- Type: Float
- Unit: Unitless score
- Example:
0.08 - Target:
< 0.1(good),0.1-0.25(needs improvement),> 0.25(poor)
core_web_vitals.inp.median
- Type: Integer
- Unit: Milliseconds
- Example:
180 - Target:
< 200(good),200-500(needs improvement),> 500(poor)
issues[].type
- Type: String
- Values:
"technical_seo","performance","accessibility","security" - Use case: Issue categorization
issues[].severity
- Type: String
- Values:
"high","medium","low" - Use case: Priority sorting
issues[].page
- Type: String (path)
- Example:
"/services","/contact" - Use case: Issue location
issues[].issue
- Type: String
- Example:
"LCP exceeds 4.0s on mobile" - Use case: Issue description
issues[].recommendation
- Type: String
- Example:
"Optimize hero image (currently 2.3MB uncompressed)" - Use case: Actionable fix guidance
issues[].impact
- Type: String
- Example:
"SEO ranking, user experience" - Use case: Business impact context
browsers_tested
- Type: Array of strings
- Values:
["chrome_desktop", "firefox_desktop", "safari_macos", "safari_ios", "edge_desktop", "chrome_android", "brave_desktop", "instagram_inapp", "facebook_inapp"] - Count: 9 browsers
- Use case: Cross-browser testing verification
tier
- Type: String
- Values:
"essential"or"pro" - Pro additions:
content_gapsarray,competitor_benchmarksarray (if Pro tier)
Solutions Token JSON Schema
Top-Level Structure
Example response for SOLUTIONS-2025-11-G6H7J:
{
"product": "solutions",
"token": "SOLUTIONS-2025-11-G6H7J",
"created_at": "2025-11-10T16:15:22Z",
"question": {
"text": "Should we invest in AI visibility optimization or traditional SEO?",
"context": "Budget: $50k, Timeline: 6 months, Current Presence Rate: 18%"
},
"recommendations": [
{
"priority": 1,
"action": "Hybrid approach: 60% AI visibility, 40% traditional SEO",
"rationale": "AI visibility directly addresses 18% Presence Rate gap. Traditional SEO provides foundation.",
"estimated_impact": "28-35% Presence Rate in 6 months",
"estimated_cost": "$30k AI visibility, $20k SEO",
"risk": "medium"
},
{
"priority": 2,
"action": "AI visibility only (100% budget)",
"rationale": "Aggressive approach for fast Presence Rate gains",
"estimated_impact": "35-42% Presence Rate in 6 months",
"estimated_cost": "$50k",
"risk": "high"
}
],
"model_perspectives": {
"cfo": {
"view": "Hybrid approach reduces risk while addressing core gap",
"concerns": ["ROI timeline", "Measurement difficulty"],
"confidence": "medium-high"
},
"coo": {
"view": "Execution complexity higher for hybrid (two parallel workstreams)",
"concerns": ["Team bandwidth", "Vendor coordination"],
"confidence": "medium"
},
"market_realist": {
"view": "Competitors at 40-60% Presence Rate. Hybrid won't close gap fast enough.",
"concerns": ["Competitive velocity", "Market timing"],
"confidence": "high"
},
"game_theorist": {
"view": "If competitors invest in AI visibility, hybrid keeps you behind. Go aggressive.",
"concerns": ["Competitive response", "First-mover advantage"],
"confidence": "high"
},
"chief_strategist": {
"view": "Hybrid aligns with risk tolerance. Pivot to aggressive if 3-month results strong.",
"concerns": ["Strategic optionality", "Mid-course correction ability"],
"confidence": "high"
},
"wildcard": {
"view": "What if AI platforms change algorithms mid-campaign? SEO foundation safer.",
"concerns": ["Platform risk", "Algorithm volatility"],
"confidence": "medium"
}
},
"risk_assessment": {
"overall_risk": "medium",
"key_risks": [
"AI platform algorithm changes",
"Competitive response faster than execution",
"Budget reallocation challenges if pivot needed"
],
"mitigation_strategies": [
"Monthly Presence Rate monitoring (Signal)",
"Quarterly strategy review with pivot option",
"Reserve 10% budget for opportunistic adjustments"
]
},
"has_quantitative_analysis": true
}
Field Reference: Solutions Tokens
product
- Type: String
- Value: Always
"solutions"for Solutions tokens
token
- Type: String
- Format:
SOLUTIONS-YYYY-MM-XXXXX - Example:
"SOLUTIONS-2025-11-G6H7J"
created_at
- Type: ISO 8601 datetime string
- Example:
"2025-11-10T16:15:22Z"
question.text
- Type: String
- Example:
"Should we invest in AI visibility optimization or traditional SEO?" - Use case: Question being analyzed
question.context
- Type: String
- Example:
"Budget: $50k, Timeline: 6 months, Current Presence Rate: 18%" - Use case: Context for recommendations
recommendations[].priority
- Type: Integer
- Range:
1toN(typically 2-5 recommendations) - Example:
1(highest priority)
recommendations[].action
- Type: String
- Example:
"Hybrid approach: 60% AI visibility, 40% traditional SEO" - Use case: Recommended action
recommendations[].rationale
- Type: String
- Example:
"AI visibility directly addresses 18% Presence Rate gap" - Use case: Why this recommendation
recommendations[].estimated_impact
- Type: String
- Example:
"28-35% Presence Rate in 6 months" - Use case: Expected outcome
recommendations[].estimated_cost
- Type: String
- Example:
"$30k AI visibility, $20k SEO" - Use case: Cost estimation
recommendations[].risk
- Type: String
- Values:
"low","medium","high" - Use case: Risk assessment
model_perspectives.{model}.view
- Type: String
- Models:
cfo,coo,market_realist,game_theorist,chief_strategist,wildcard - Example:
"Hybrid approach reduces risk while addressing core gap" - Use case: Model-specific perspective
model_perspectives.{model}.concerns
- Type: Array of strings
- Example:
["ROI timeline", "Measurement difficulty"] - Use case: Model-specific concerns
model_perspectives.{model}.confidence
- Type: String
- Values:
"low","medium","medium-high","high" - Use case: Model confidence level
risk_assessment.overall_risk
- Type: String
- Values:
"low","medium","high" - Use case: Overall risk level
risk_assessment.key_risks
- Type: Array of strings
- Example:
["AI platform algorithm changes", "Competitive response faster than execution"] - Use case: Risk identification
risk_assessment.mitigation_strategies
- Type: Array of strings
- Example:
["Monthly Presence Rate monitoring (Signal)", "Reserve 10% budget for adjustments"] - Use case: Risk mitigation planning
has_quantitative_analysis
- Type: Boolean
- Values:
trueorfalse - Use case: Whether Solutions included linked Signal/Scan token data for quantitative analysis
Common Integration Patterns
Pattern 1: Quarterly Tracking Dashboard
Use case: Track Presence Rate improvements over time
Fields needed:
token(identifier)created_at(timestamp)metrics.presence_rate(core metric)metrics.authority_score(positioning)competitors[].presence_rate(competitive context)
Code example (Python):
import requests
import pandas as pd
tokens = ["SIG-2025-02-A1B2C", "SIG-2025-05-D3E4F", "SIG-2025-08-G5H6J", "SIG-2025-11-K7L8M"]
data = []
for token in tokens:
response = requests.get(f"https://api.surmado.com/intelligence/{token}")
json_data = response.json()
data.append({
"date": json_data["created_at"][:10], # Extract date only
"presence_rate": json_data["metrics"]["presence_rate"] * 100,
"authority_score": json_data["metrics"]["authority_score"],
"top_competitor": json_data["competitors"][0]["presence_rate"] * 100 if json_data["competitors"] else 0
})
df = pd.DataFrame(data)
print(df)
# Output:
# date presence_rate authority_score top_competitor
# 0 2025-02-15 28.0 68 54.0
# 1 2025-05-20 34.0 72 52.0
# 2 2025-08-18 42.0 78 51.0
# 3 2025-11-10 48.0 82 49.0
Pattern 2: Platform-Specific Optimization
Use case: Identify which AI platforms need improvement
Fields needed:
platform_variance.{platform}.presence_rateplatform_variance.{platform}.authority_score
Code example (JavaScript):
const token = "SIG-2025-11-A1B2C";
fetch(`https://api.surmado.com/intelligence/${token}`)
.then(response => response.json())
.then(data => {
const platforms = data.platform_variance;
// Find weakest platform
let weakest = { name: "", rate: 1.0 };
for (const [platform, metrics] of Object.entries(platforms)) {
if (metrics.presence_rate < weakest.rate) {
weakest = { name: platform, rate: metrics.presence_rate };
}
}
console.log(`Focus optimization on: ${weakest.name} (${(weakest.rate * 100).toFixed(1)}% Presence Rate)`);
// Output: "Focus optimization on: claude (38.0% Presence Rate)"
});
Pattern 3: Competitive Alerts
Use case: Alert when competitor surpasses you
Fields needed:
metrics.presence_rate(your rate)competitors[].presence_rate(competitor rates)competitors[].rank(competitive ranking)
Code example (Python for automation):
import requests
def check_competitive_position(token):
response = requests.get(f"https://api.surmado.com/intelligence/{token}")
data = response.json()
your_rate = data["metrics"]["presence_rate"]
# Find your competitive rank
your_rank = None
for idx, comp in enumerate(data["competitors"]):
if comp["presence_rate"] < your_rate:
your_rank = idx + 1 # You rank above this competitor
break
if your_rank is None:
your_rank = len(data["competitors"]) + 1 # You rank below all competitors
if your_rank > 3:
return {
"alert": True,
"message": f"You rank #{your_rank} in competitive Presence Rate. Top 3 competitors: {', '.join([f'{c['name']} ({c['presence_rate']*100:.1f}%)' for c in data['competitors'][:3]])}"
}
return {"alert": False}
# Run weekly via cron
result = check_competitive_position("SIG-2025-11-A1B2C")
if result["alert"]:
print(f"{result['message']}")
# Send email/Slack notification
Pattern 4: Scan Issue Prioritization
Use case: Sort Scan issues by severity and impact
Fields needed:
issues[].severity(high/medium/low)issues[].type(category)issues[].page(location)
Code example (Python):
import requests
token = "SCAN-2025-11-D4E5F"
response = requests.get(f"https://api.surmado.com/intelligence/{token}")
data = response.json()
# Filter high-severity issues
high_severity = [issue for issue in data["issues"] if issue["severity"] == "high"]
# Group by type
from collections import defaultdict
by_type = defaultdict(list)
for issue in high_severity:
by_type[issue["type"]].append(issue)
# Print prioritized list
print("High-Priority Issues:")
for issue_type, issues in by_type.items():
print(f"\n{issue_type.upper()} ({len(issues)} issues):")
for issue in issues:
print(f" - {issue['page']}: {issue['issue']}")
Pattern 5: Solutions Risk Dashboard
Use case: Visualize risk assessment from Solutions
Fields needed:
recommendations[].actionrecommendations[].riskrisk_assessment.key_risks
Code example (JavaScript for dashboard):
const token = "SOLUTIONS-2025-11-G6H7J";
fetch(`https://api.surmado.com/intelligence/${token}`)
.then(response => response.json())
.then(data => {
// Create risk matrix
const riskMatrix = data.recommendations.map(rec => ({
action: rec.action,
impact: rec.estimated_impact,
risk: rec.risk,
cost: rec.estimated_cost
}));
// Filter by acceptable risk level
const acceptable = riskMatrix.filter(r => r.risk === "low" || r.risk === "medium");
console.log("Acceptable Risk Options:");
acceptable.forEach(option => {
console.log(`${option.action} (${option.risk} risk, ${option.cost})`);
});
});
Error Handling
HTTP Status Codes
200 OK: Token found, JSON returned 404 Not Found: Token doesn’t exist (check format) 500 Internal Server Error: API issue (retry after 2-5 seconds)
Example Error Response
{
"error": "Token not found",
"token": "SIG-2025-99-ZZZZZ",
"message": "Intelligence Token does not exist or has been deleted"
}
Recommended Error Handling (Python)
import requests
import time
def fetch_with_retry(token, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.get(
f"https://api.surmado.com/intelligence/{token}",
timeout=10
)
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
raise ValueError(f"Token {token} not found")
elif response.status_code == 500:
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
continue
else:
raise Exception("API error after retries")
except requests.exceptions.Timeout:
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
else:
raise Exception("Request timeout after retries")
raise Exception("Failed to fetch data")
# Usage
try:
data = fetch_with_retry("SIG-2025-11-A1B2C")
print(data["metrics"]["presence_rate"] * 100)
except ValueError as e:
print(f"Invalid token: {e}")
except Exception as e:
print(f"API error: {e}")
Data Types Summary
All numeric values are designed for computation (not display):
| Field | Type | Format | Display Conversion |
|---|---|---|---|
| presence_rate | Float | 0.0-1.0 | × 100 for percentage |
| authority_score | Integer | 0-100 | Direct display |
| ghost_influence | Float | 0.0-1.0 | × 100 for percentage |
| category_share | Float | 0.0-1.0 | × 100 for percentage |
| overall_score | Integer | 0-100 | Direct display |
| lcp | Float | Seconds | Direct display with “s” |
| cls | Float | Unitless | Direct display |
| inp | Integer | Milliseconds | Direct display with “ms” |
Rate Limits
Current: No rate limits (API in production with unlimited access)
Future (if needed):
- 100 requests/minute per token
- 10,000 requests/day per token
Recommendation: Cache responses when possible (data doesn’t change after report creation)
Frequently Asked Questions
Can I access historical token data years later?
Yes. Intelligence Tokens never expire. API access is permanent.
Do I need to store the entire JSON response?
Only if you need historical data. You can extract specific fields and store them in your database instead of the full JSON.
What if a field is null?
Some fields are null when data doesn’t apply:
authority_score:nullifpresence_rate == 0(no mentions to analyze positioning)- Competitor
authority_score:nullif competitor has 0% presence rate
Can I share Intelligence Token API responses?
You can share within your organization. Avoid sharing tokens publicly (anyone with token can access data).
Does the API support bulk requests?
Not currently. Make individual requests per token. If you need bulk access for 100+ tokens, contact hi@surmado.com for options.
Need API integration help? See API Integration Overview for Zapier/Make/n8n workflows, or contact hi@surmado.com for custom integration support.
Was this helpful?
Thanks for your feedback!
Have suggestions for improvement?
Tell us moreHelp Us Improve This Article
Know a better way to explain this? Have a real-world example or tip to share?
Contribute and earn credits:
- Submit: Get $25 credit (Signal, Scan, or Solutions)
- If accepted: Get an additional $25 credit ($50 total)
- Plus: Byline credit on this article