API Reference

The Uncover API lets you surface real user pain points from Reddit, HackerNews, and X. Send a query, get back structured problems, sentiment analysis, trends, and a summary. Credits-based — no subscriptions required.

Base URL
https://api.uncover.thealxlabs.ca
Authentication
Bearer token (API key)
Content-Type
application/json
Rate limit
60 req/min · 10 searches/min
bash
# Quick start
curl -X POST https://api.uncover.thealxlabs.ca/api/search \
  -H "Authorization: Bearer sk_live_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"query":"password manager frustrations","sources":["reddit","hackernews"]}'

Authentication

All authenticated endpoints require a Bearer token in the Authorization header. API keys follow the format sk_live_ followed by a 32-character hex string.

bash
# Include in every request
-H "Authorization: Bearer sk_live_API_KEY_HERE"

Get your API key by signing up at uncover.thealxlabs.ca/login. Keys are hashed server-side — you must save your key when it is first shown.

Endpoints

POST/api/auth/signuppublic

Create a new user account and get an API key.

Request body

ParameterTypeRequiredDescription
emailstringrequiredYour email address
passwordstringrequiredMinimum 8 characters
namestringoptionalDisplay name (optional)
bash
curl -X POST https://api.uncover.thealxlabs.ca/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"yourpassword","name":"Alex"}'
json
{
  "user": { "id": "clx...", "email": "you@example.com", "name": "Alex" },
  "apiKey": { "id": "clx...", "key": "sk_live_...", "name": "Default Key" }
}
POST/api/auth/signinpublic

Verify credentials. Returns key metadata (not the raw key — save it on signup).

bash
curl -X POST https://api.uncover.thealxlabs.ca/api/auth/signin \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"yourpassword"}'
json
{
  "user": { "id": "clx...", "email": "you@example.com" },
  "apiKeys": [{ "id": "clx...", "name": "Default Key", "createdAt": "...", "lastUsed": null }],
  "message": "1 key(s) found. Use your saved sk_live_ key to authenticate."
}
GET/api/auth/keys

List all API keys for your account.

bash
curl https://api.uncover.thealxlabs.ca/api/auth/keys \
  -H "Authorization: Bearer sk_live_API_KEY_HERE"
json
{
  "apiKeys": [
    { "id": "clx...", "name": "Default Key", "createdAt": "2026-01-01T00:00:00Z", "lastUsed": null }
  ]
}
POST/api/auth/keys

Create a new API key.

ParameterTypeRequiredDescription
namestringoptionalKey label (e.g. "Production")
bash
curl -X POST https://api.uncover.thealxlabs.ca/api/auth/keys \
  -H "Authorization: Bearer sk_live_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"name":"Production"}'
json
{ "id": "clx...", "key": "sk_live_...", "name": "Production" }
DELETE/api/auth/keys/:id

Revoke an API key. Irreversible.

bash
curl -X DELETE https://api.uncover.thealxlabs.ca/api/auth/keys/KEY_ID \
  -H "Authorization: Bearer sk_live_API_KEY_HERE"
json
{ "deleted": true }
GET/api/search/:requestId

Retrieve a completed search result by ID. Must be your own request.

bash
curl https://api.uncover.thealxlabs.ca/api/search/REQUEST_ID \
  -H "Authorization: Bearer sk_live_API_KEY_HERE"
GET/api/search/history

Get your recent search history.

ParameterTypeRequiredDescription
limitnumberoptionalNumber of results (1–50, default 10)
bash
curl "https://api.uncover.thealxlabs.ca/api/search/history?limit=5" \
  -H "Authorization: Bearer sk_live_API_KEY_HERE"
POST/api/search/costpublic

Preview the credit cost of a search before running it. No credits deducted.

bash
curl -X POST https://api.uncover.thealxlabs.ca/api/search/cost \
  -H "Content-Type: application/json" \
  -d '{"sources":["reddit","twitter","hackernews"],"limit":30}'
json
{ "credits": 3 }
GET/api/results/:requestIdpublic

Fetch a search result publicly — no authentication required. Read-only.

bash
curl https://api.uncover.thealxlabs.ca/api/results/REQUEST_ID
json
{
  "requestId": "clx...",
  "query": "password manager frustrations",
  "sources": ["reddit"],
  "status": "completed",
  "summary": "...",
  "problems": [...],
  "trends": [...],
  "createdAt": "2026-01-01T00:00:00Z"
}
GET/api/billing/status

Get your credit balance, plan, available packs, and recent transactions.

bash
curl https://api.uncover.thealxlabs.ca/api/billing/status \
  -H "Authorization: Bearer sk_live_API_KEY_HERE"
json
{
  "plan": "payg",
  "credits": 48,
  "totalSpent": 5.00,
  "totalSearches": 12,
  "isSubscriber": false,
  "subscription": null,
  "packs": [
    { "key": "starter", "name": "Starter Pack", "credits": 50, "price": "$5.00", "perSearch": "$0.100" }
  ],
  "subscriptionPlans": [...],
  "recentTransactions": [...]
}
POST/api/billing/checkout

Create a Stripe checkout session to buy a credit pack. Returns a URL to redirect to.

ParameterTypeRequiredDescription
packstringrequired"starter" | "growth" | "pro_pack" | "scale"
bash
curl -X POST https://api.uncover.thealxlabs.ca/api/billing/checkout \
  -H "Authorization: Bearer sk_live_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"pack":"pro_pack"}'
json
{ "url": "https://checkout.stripe.com/...", "sessionId": "cs_...", "pack": {...} }
POST/api/billing/subscribe

Start a monthly subscription. Returns a Stripe checkout URL.

ParameterTypeRequiredDescription
planstringrequired"builder" | "team" | "enterprise"
bash
curl -X POST https://api.uncover.thealxlabs.ca/api/billing/subscribe \
  -H "Authorization: Bearer sk_live_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"plan":"team"}'
POST/api/billing/portal

Open the Stripe billing portal to manage or cancel your subscription.

bash
curl -X POST https://api.uncover.thealxlabs.ca/api/billing/portal \
  -H "Authorization: Bearer sk_live_API_KEY_HERE"
json
{ "url": "https://billing.stripe.com/..." }
POST/api/billing/redeem

Redeem a promo code to add free credits.

ParameterTypeRequiredDescription
codestringrequiredPromo code (e.g. UNCOVER-LAUNCH)
bash
curl -X POST https://api.uncover.thealxlabs.ca/api/billing/redeem \
  -H "Authorization: Bearer sk_live_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"code":"UNCOVER-LAUNCH"}'
json
{ "success": true, "credits": 50, "message": "50 credits added to your account" }
GET/api/admin/stats

Platform-wide stats. Requires X-Admin-Password header.

bash
curl https://api.uncover.thealxlabs.ca/api/admin/stats \
  -H "X-Admin-Password: YOUR_ADMIN_PASSWORD"
POST/api/admin/promo

Create a promo code. Requires X-Admin-Password header.

ParameterTypeRequiredDescription
creditsnumberrequiredCredits to grant on redemption
codestringoptionalCustom code (auto-generated if omitted)
maxUsesnumberoptionalMax total redemptions (default 1)
expiresInDaysnumberoptionalDays until expiry
bash
curl -X POST https://api.uncover.thealxlabs.ca/api/admin/promo \
  -H "X-Admin-Password: YOUR_ADMIN_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{"credits":25,"maxUses":100,"code":"LAUNCH25","expiresInDays":30}'

Credit Pricing

Credit cost is calculated dynamically based on what you search. The formula:

cost = 1 + (sources − 1) + floor((limit − 1) / 10) + floor(activeFilters / 2)
FactorCredit impactExample
Base (1 source, up to 10 posts)+1reddit, 10 posts = 1 cr
Additional source+1 eachreddit + hackernews = 2 cr
Additional 10 posts+1 per tier20 posts = +1, 30 posts = +2
Filters (minUpvotes, maxAge, excludeKeywords, excludeSubreddits)+1 per 2 filters2 filters = +1 cr
Custom URL search (base)2 cr base1 URL = 2 cr
Extra custom URLs+1 each above 13 URLs = 4 cr
Caching: Identical searches within a short window are served from cache at 0 credits. The request is still logged, but no credits are deducted.

Credit packs

PackCreditsPricePer search
Starter50$5$0.10
Growth200$15$0.075
Pro500$29$0.058
Scale2,000$79$0.040

Subscriptions

PlanCredits/moPricePer search
Builder300$19/mo$0.063
Team1,000$49/mo$0.049
Enterprise5,000$149/mo$0.030

TypeScript SDK

Install the official SDK from npm:

bash
npm install @uncover/sdk

Basic usage

typescript
import { Uncover } from "@uncover/sdk";

const client = new Uncover("sk_live_API_KEY_HERE");

const result = await client.search({
  query: "password manager frustrations",
  sources: ["reddit", "hackernews"],
  limit: 20,
});

console.log(result.summary);
console.log(result.problems);
console.log(result.trends);

With options

typescript
const result = await client.search({
  query: "CRM software complaints",
  sources: ["reddit", "twitter"],
  limit: 30,
  options: {
    minUpvotes: 10,
    maxAgeHours: 720,           // last 30 days
    excludeSubreddits: ["AskReddit"],
    excludeKeywords: ["spam", "ad"],
  },
});

Get search by ID

typescript
const status = await client.getSearchStatus("REQUEST_ID");
console.log(status.status); // "completed" | "failed" | "pending"

SDK types

typescript
import type { SearchRequest, SearchResponse, Problem } from "@uncover/sdk";

interface Problem {
  text: string;
  frequency: number;               // 1–10
  sentiment: "frustrated" | "confused" | "disappointed" | "neutral";
}

interface SearchResponse {
  requestId: string;
  status: "pending" | "processing" | "completed" | "failed";
  query: string;
  sources: ("reddit" | "twitter" | "hackernews")[];
  postsAnalyzed?: number;
  problems?: Problem[];
  summary?: string;
  trends?: string[];
  cost?: number;
  credits?: { remaining: number };
}

CLI

The CLI lets you run searches and manage your account from the terminal.

bash
npm install -g @uncover/cli

Authentication

bash
# Paste your API key directly
uncover login --key sk_live_API_KEY_HERE

# Or verify with email first (then paste key)
uncover login

Run a search

bash
# Basic search
uncover scrape "password manager frustrations"

# Multiple sources
uncover scrape "CRM complaints" --sources reddit,hackernews

# With filters
uncover scrape "Notion UX issues" \
  --sources reddit \
  --limit 30 \
  --min-upvotes 10 \
  --max-age 720

# Raw JSON output
uncover scrape "Slack issues" --json

Account management

bash
# Check credits and plan
uncover status

# Recent search history
uncover history --limit 10

# List API keys
uncover keys

# Sign out
uncover logout

Available flags

FlagDefaultDescription
--sourcesredditComma-separated: reddit,twitter,hackernews
--limit20Posts to analyze (1–50)
--exclude-subredditsComma-separated subreddits to skip
--exclude-keywordsKeywords to filter out
--min-upvotes0Minimum post upvotes
--max-ageMax post age in hours
--jsonfalseOutput raw JSON

Errors & Rate Limits

All errors return JSON with an error field.

json
{ "error": "Insufficient credits", "credits": 0, "required": 2 }

HTTP status codes

CodeMeaning
200Success
201Created (signup, key creation)
400Bad request — invalid parameters
401Unauthorized — missing or invalid API key
402Insufficient credits
403Forbidden — accessing another user's resource
404Not found
409Conflict — email already registered, code already redeemed
410Gone — promo code expired or fully redeemed
429Rate limit exceeded — wait and retry
500Internal server error

Rate limits

EndpointLimit
All API endpoints60 requests / minute
POST /api/search10 requests / minute
POST /api/auth/signup10 requests / minute
Tip: Use POST /api/search/cost before running a search to preview the credit cost. Cached results are free — identical searches within a short window cost 0 credits.