Copy the block below and paste it into your coding agent (Claude Code,
Cursor, ChatGPT with tools, anything that can run shell commands). It
walks the agent through signup, testing a call, and, when you're ready, wiring up billing. The API works headlessly, and the passwordless
/app dashboard is available for people who want it.
You are setting up programmatic access to Uniqueness Engine (https://uniquenessengine.com): an API that takes a LinkedIn URL and returns fact-checked personal context for cold email, mid-funnel, and CSM/CX, centered on hobbies and personal interests that scrapes and contact-data tools miss. Every fact carries a source link and the quote it came from. Broader interest signals and the personality read are clearly marked as a read, not a fact. Profiles are read from multiple independent public-data providers with automatic fallback; if fewer than 3 personal facts verify, additional verified public-source lanes engage automatically. Every candidate must pass the same identity and fact checks. Follow these steps in order. Where marked [ASK USER], stop and get input from the person you're working for before continuing, do not guess or fabricate that input.
0) FREE VALIDATION ONLY: do not pretend a live enrich completed without a paid key.
Free validation = kitchen-sink only. Unauthenticated POST /api/enrich returns 401. Never invent personal context.
a) curl -sS https://uniquenessengine.com/api/health
b) curl -sS "https://uniquenessengine.com/api/examples/kitchen-sink?detail=compact"
Assert: mode=="synthetic_fixture", billing.charged==false, not_a_real_person==true, every facts[] row has confidence_label and NO band.
c) Fetch https://uniquenessengine.com/openapi.json and validate the kitchen-sink shape against the CompactBrief / fact schema (confidence_label present; band absent).
Only after a–c, continue to signup → claim key → human checkout (402) → enrich → poll.
1) SIGN UP: named email verification. Keep both returned values in this trusted process; they are secrets, but neither is an API key.
SIGNUP_RESPONSE="$(curl -sS -X POST https://uniquenessengine.com/api/signup \
-H 'content-type: application/json' \
-d '{"email":"[ASK USER for their email]","client_name":"[ASK USER for a client name]","device_name":"[ASK USER for a device name]"}')"
If signup returns HTTP 503 with error "verification_delivery_failed", no usable polling secret or API key was issued. Honor Retry-After, then repeat this signup request.
TRANSACTION_ID="$(printf '%s' "$SIGNUP_RESPONSE" | jq -r '.transaction_id')"
POLLING_TOKEN="$(printf '%s' "$SIGNUP_RESPONSE" | jq -r '.polling_token')"
Do not print, email, log, or put the polling token in an agent transcript. Approval creates a new revocable API key once; it grants no free live credits.
2) VERIFY, CLAIM ONCE, then store the key in a secret manager or trusted environment.
A human approves the named device from their email. Poll with BOTH retained values until status is "approved":
curl -sS "https://uniquenessengine.com/api/signup/verification/$TRANSACTION_ID" \
-H "x-verification-token: $POLLING_TOKEN"
Pending, denied, expired, and already_claimed do not yield a key. Only after approved, call this exactly once:
CLAIM_RESPONSE="$(curl -sS -X POST "https://uniquenessengine.com/api/signup/verification/$TRANSACTION_ID/claim" \
-H "x-verification-token: $POLLING_TOKEN")"
export UNIQUENESS_API_KEY="$(printf '%s' "$CLAIM_RESPONSE" | jq -r '.api_key')"
Never echo or relay the key to the user/agent transcript. Then verify the account:
curl https://uniquenessengine.com/api/account -H "authorization: Bearer $UNIQUENESS_API_KEY"
This confirms total spendable credit and provenance.
2a) SEE PERSONAL CONTEXT INSTANTLY: free example fixture, no key, no credits (already done in step 0; re-run if needed).
Prefer the compact shape agents should use in production tooling:
curl "https://uniquenessengine.com/api/examples/kitchen-sink?detail=compact"
Expected: HTTP 200 with "mode":"synthetic_fixture", "not_a_real_person":true, "billing":{"charged":false}, identity.full_name, facts[] (each with evidence_quote, source_url, confidence, confidence_label; no band), personality, and discovered_handles (platform → profile URL map; present on compact). This is a fixture, never a real resolution, real lookups run through /api/enrich (step 3) only after a key + paid credit.
3) TEST the user's own real LinkedIn URL. [ASK USER] for the LinkedIn URL unless they already gave one. A fresh personal context usually runs 45-90s (rarely up to ~3 min), so the API is ASYNCHRONOUS: submit, then poll.
Submit:
curl -X POST https://uniquenessengine.com/api/enrich \
-H "authorization: Bearer $UNIQUENESS_API_KEY" \
-H 'content-type: application/json' \
-d '{"linkedin_url":"[ASK USER for their LinkedIn URL]","detail":"compact"}'
This returns 202 {"job_id":"...","status":"queued"} (or 200 {"status":"done","brief":{...}} if it was cached: then you're done, skip polling).
Poll every ~5s until status is done | refused | failed:
JOB_ID="<from submit response>"
curl "https://uniquenessengine.com/api/jobs/$JOB_ID" -H "authorization: Bearer $UNIQUENESS_API_KEY"
When "status":"done", the personal context is at .result. On cache-hit submit, the personal context is at top-level .brief. Confirm it has "status":"ok" and a facts array (each fact carries the quote it came from in evidence_quote and its source link in source_url). Broader interest signals and the personality read are clearly marked as a read, not a fact. Every fact also carries a "category" (e.g. "family_or_children", "health", "authored_work") so you know what KIND of fact it is; sensitive facts may carry "special_category":true (health/recovery/religion/politics/protected attributes): still real and surfaced, never blocked. We verify and LABEL facts; we don't tell you what's safe to send, how you use a fact is your call, informed by the category. (The old "safe_to_use_in_outreach" stamp, the "band" verdict, the "outreach_angles"/"gift_hook" fields and the six split arrays were all removed on 2026-08-03, see ADR-0025. Every fact is now in one "facts" array.)
Response paths:
- HTTP 200 + status:"done" + brief: cache hit; no poll; costs 1 credit unless this account already unlocked the person.
- HTTP 202/job_id + status:"queued": poll GET /api/jobs/$JOB_ID every ~5s.
- Poll status:"refused": identity gate failed; .result.status is needs_review; not charged.
- HTTP 402 payment_required: paid admission did not have enough spendable credit. Show the offered pack terms and ask the human before opening Checkout; never purchase, save a method, enable auto-recharge, or replay the target by inference. See step 5.
3b) TEST a refusal while credits_remaining >= 1 (confirms the "we never invent it" behavior, and that it consumes no credit). With 0 credits, paid admission returns the canonical HTTP 402 before live work, so this check requires one available credit to reserve and release.
curl -X POST https://uniquenessengine.com/api/enrich \
-H "authorization: Bearer $UNIQUENESS_API_KEY" \
-H 'content-type: application/json' \
-d '{"name":"Zzqrx Nonexistentperson","company":"NotARealCompany9999"}'
Poll the returned job_id. Confirm the job ends "status":"refused" (its .result has "status":"needs_review", usage.credits_charged 0). The exact reserved allocation is released. This is correct behavior, not an error, the engine refuses rather than guessing when it can't verify a real person.
4) CHOOSE how you'll call it going forward (pick what fits your environment, all three call the same API):
- Direct API (works everywhere, no install): repeat the submit→poll from step 3. The deprecated /api/brief compatibility alias now follows the same async paid-admission contract; prefer /api/enrich for new integrations.
- CLI: npm install -g uniqueness (handles submit+poll for you)
uniqueness example (free synthetic sample personal context; no key, no charge; confirms the CLI works)
uniqueness context --linkedin-url https://www.linkedin.com/in/ --json
uniqueness batch preflight --file people.json --json (estimate only; starts no work)
uniqueness batch submit --file people.json --json (starts paid batch work)
uniqueness feedback up|down --canonical-id (rate a personal context 👍/👎)
Agent skill: https://uniquenessengine.com/SKILL.md
uniqueness account
uniqueness health
uniqueness update (global install only; asks before installing. npx already resolves latest)
uniqueness billing status|packs|subscriptions|portal
uniqueness billing auto-recharge enable|disable|retry (every change requires explicit human confirmation)
- Hosted MCP (primary; get_personal_context plus job, batch, result, export, cancellation, retry, billing, preflight, and feedback tools):
{ "mcpServers": { "uniqueness": { "url": "https://uniquenessengine.com/mcp", "headers": { "Authorization": "Bearer uq_live_..." } } } }
Compatible hosted fixes require no reinstall. Use npx -y uniqueness-mcp@latest only as a local stdio fallback; its signup tools configure that running process only.
MCP stores no unpaid target. After human-approved Checkout, resume_personal_context (alias resume_connection_brief) requires the host to resupply the original target, payment_required.retry.idempotency_key, and payment_required.credits.available; the API rejects a mismatched retry identity.
Smoke test after adding config: call get_personal_context with the user's own linkedin_url only when paid credit is available, and confirm it returns personal context JSON. To inspect the shape first, GET the fictional static fixture at https://uniquenessengine.com/api/examples/kitchen-sink. Config-only is not verified.
After a personal context, you can call submit_feedback with rating="up"|"down" and the personal context's identity.canonical_id to help the engine improve (never charges/refunds a credit).
4b) BATCH PREFLIGHT for lists. Estimate before submitting a batch so you know likely credit usage:
curl -X POST https://uniquenessengine.com/api/enrich/batch \
-H "authorization: Bearer $UNIQUENESS_API_KEY" \
-H 'content-type: application/json' \
-d '{"estimate_only":true,"profiles":[{"linkedin_url":"https://www.linkedin.com/in/"}]}'
Read estimate.max_charge, estimate.likely_charge, estimate.balance, estimate.need_topup, and estimate.shortfall_if_all_resolve. likely_charge is advisory and may understate charges for globally cached people; use max_charge as the safe ceiling. Do not fire dozens of parallel POST /api/enrich calls; use the batch endpoint or sequential submit with balance checks.
5) BILLING: Jordan Ellis is the only free experience and is fictional static data. Every real enrichment requires one paid credit and always uses full-quality written enrichment. The one-time Intro 10 is ten credits for a $5 USD subtotal plus applicable tax (first credit-pack purchase only); larger packs are 20/$7.40, 50/$18.50, and 100/$37. Credits never expire. Existing subscriptions are unchanged. Auto-recharge is separate explicit consent, off by default; saving a payment method does not enable it.
GET https://uniquenessengine.com/api/billing/catalog is the read-only source of truth for pack and subscription terms. It contains no account, target, credential, or purchase action.
The only purchase actions come from a canonical HTTP 402 payment_required response: payment_required.recommended_offer.checkout_url opens the offered target-free pack, and payment_required.billing_url opens the target-free pack selector. First show the returned credits, tax-exclusive subtotal, applicable-tax notice, and expiry. Then [ASK USER] for explicit consent before opening either URL. Never use a payment-method setup route or treat a saved method as a purchase.
After the human completes Checkout, do not assume payment succeeded. Confirm the service reports new spendable credit, then resubmit only with payment_required.retry.idempotency_key before its expiry. If it expires, submit a new request; never replay a target by inference.
To cancel or update the card later: curl -X POST https://uniquenessengine.com/api/billing/portal → returns a Stripe-hosted management link.
6) DONE. Call POST /api/enrich (then poll GET /api/jobs/:id) with any linkedin_url (or name + company) from here on. An exact credit allocation is reserved on submit and released on refusal/wrong-person/no-result/failure. A successful first unlock costs 1 credit, including a global cache hit; a same-account re-pull costs 0 and reports usage.cache_status=hit unless refresh:true on POST /api/enrich (CLI --refresh, MCP refresh:true). Batch rejects refresh. Only claim a rerun when usage.refresh_executed is true or a new job_id / generated_at appears. Check GET /api/account any time for balance and billing status.
If a key ever leaks, revoke that named key in Account and create a replacement there. The new secret is shown once; existing keys are never re-disclosed.
Every endpoint above is real and live: this isn't aspirational copy, it's the actual API.
{
"status": "ok",
"identity": { "full_name": "...", "title": "...", "company": "...", "status": "resolved" },
"facts": [
{ "claim": "...", "evidence_quote": "quote from the source", "source_url": "...",
"connection_type": "personal_signal", "category": "family_or_children",
"special_category": false, "confidence": 0.65, "confidence_label": "high",
"mentionability": 0.9, "sensitivity_score": 0.05, "verdict": "entailed" }
],
"personality": { "archetype": "...", "disc_label": "...", "how_to_communicate": ["..."], "predicted": true },
"detail": "compact",
"usage": { "cache_status": "hit|miss", "credits_charged": 1, "credits_remaining": 9 }
}
# Agents: prefer detail=compact (MCP defaults to compact). HTTP production default remains full until the compact-default cutoff is armed; pass detail=full for provenance sub-scores.
Personal vs. professional signal is split via
connection_type. Facts in facts
are click-to-verify through evidence_quote +
source_url. They are separate from the broader interest
signals in aggregated_interests, which are clearly marked
as a read, not a fact (?detail=full only). New
discovery denies FEC, court-record, obituary, wedding, and
people-search URLs, strips addresses at ingestion, and drops pages
that never name the target.
category / special_category label what
KIND of fact it is (sensitivity is a label, not a block:
only home/physical addresses and private contact info are hard
blocked). We verify and label; we don't tell you what's safe to send:
the removed safe_to_use_in_outreach,
band, outreach_angles and
gift_hook are never returned (ADR-0025). Full contract:
/openapi.json.
- A Checkout action can never be completed by an agent alone. Only after explicit human consent, surface the 402's recommended_offer.checkout_url or billing_url; Stripe requires a real human to finish on its hosted page. Do not claim a purchase succeeded until the service reports spendable credit. - needs_review responses are not a bug, the engine refuses rather than guesses when it can't confirm identity or confirm a fact in public text. Don't retry expecting a different answer; the signal genuinely isn't there. - Rate limits exist per API key (burst + sustained) and per signup IP. A 429 means slow down, not "try a different key." - Never put UNIQUENESS_API_KEY in client-side/browser code, it's a server-side secret. If it ends up in a repo, log, or anywhere public, a human rotates it at /account. Do not run uniqueness account rotate-key or read api_key from its output. - Call /api/* directly, not the website's HTML pages, those sit behind bot protection and can 403 a bot-like User-Agent, while API routes don't. Sending a descriptive User-Agent naming your tool/agent is good citizenship and helps us debug, though it isn't required, default library User-Agents aren't blocked on /api/*.