API reference
Company Intel API
Post a domain, get a firmographic dossier where every field carries the live URL it was read from. One synchronous call, JSON in and out. Three rails share one meter: 12 Ounie credits per dossier on REST and MCP, $0.144 USDC per dossier keyless over x402.
Quickstart
curl -X POST https://company.ounie.com/api/dossiers \
-H "Authorization: Bearer cin_live_…" \
-H "Content-Type: application/json" \
-d '{"domain":"stripe.com"}'The dossier comes back on the same request — expect 15–45 seconds, since it renders up to 5 pages. There is no job to poll.
Authentication
Three credentials work, in this order of precedence. Every one of them spends the same Ounie wallet, and none of them can overdraw it: a caller short on credits gets a 402 naming the shortfall, never a silent debt.
- Session cookie. The shared
.ounie.comcookie. This is what the dashboard uses; you get it by signing in. - App key.
Authorization: Bearer cin_live_…, minted at /dashboard/api-keys. Five active per account; only its hash is stored, so the token is shown once. - Fleet master key. Your ounie.com
ounie_live_…developer key, if you have turned on “Use across Ounie apps” in your ounie.com settings. One key for every Ounie app.
Authorization header — the Ounie AI Team’s manual MCP entry, for one — can pass ?api_key=cin_live_… on the URL instead. It works on every REST route and on the MCP transport.POST /api/dossiers
Build one dossier. Costs 12 credits; thin results refund in full.
| Field | Type | Notes |
|---|---|---|
| domain | string, required | A bare domain or a full URL. url is accepted as an alias. |
| sections | string[], optional | Any of identity, size, stack, funding, contact. Narrows the fetches, so it returns faster. The price is the same. |
| recency_days | integer, optional | Only count funding and news coverage published in this window. Max 1825. |
sections value, a malformed domain, an IP literal, a non-standard port, or a hostname that resolves to a private network all return 400 before any work happens. Nothing is reserved and nothing is charged.The response
{
"ok": true,
"dossier": {
"id": "…", "domain": "stripe.com", "status": "succeeded",
"name": "Stripe",
"name_source": "https://stripe.com/",
"description": "Stripe is a financial infrastructure platform…",
"description_source": "https://stripe.com/",
"description_derived": false, // false = the site's own meta description
"industry": "payments infrastructure",
"industry_evidence": { "quote": "…", "source": "https://stripe.com/" },
"size_signals": {
"headcount_hints": [ { "text": "…", "source": "https://…/about" } ],
"careers_open_roles": 214, // null when we could not tell
"careers_source": "https://…/jobs"
},
"socials": { "linkedin": "…", "x": "…", "github": "…" },
"tech_stack": [
{ "name": "Cloudflare", "category": "CDN",
"evidence": "server: cloudflare", "kind": "header",
"source": "https://stripe.com/" }
],
"funding_mentions": [
{ "title": "…", "url": "https://…", "date": "2025-06-10", "quote": "…" }
],
"key_pages": [ { "path": "/", "url": "https://…", "title": "…", "words": 1420 } ],
"contact_surface": {
"emails": [ { "value": "…", "source": "https://…" } ],
"phones": [ { "value": "…", "source": "https://…" } ],
"addresses": [ { "value": "…", "source": "https://…" } ]
},
"confidence": 0.85, // how much RESOLVED, not how likely it is right
"signals": 8, // of nine signal groups
"pages_fetched": 5,
"dropped_claims": 1, // model claims deleted for lacking a source
"thin": false,
"credits_spent": 12
}
}- An absent field is null or an empty array. It is never filled with a plausible value. Treat it as “not published”.
careers_open_rolesis null, not zero, when we could not tell. Zero would be a claim we cannot support.confidencemeasures coverage. It is the weighted share of the nine signal groups that resolved — a deterministic function of what was found, not a probability that the dossier is correct.
The sourcing contract
This is the part worth reading before you trust the output. The dossier is built two different ways, and the difference matters.
| Produced by | Fields | Guarantee |
|---|---|---|
| read | emails, phones, socials, tech stack, live job links, key pages | Read out of the fetched pages with regular expressions and header inspection. Each value is a substring of something we downloaded, or the literal header line that produced it. No model is involved. |
| model | name, description, industry, headcount phrasing, postal addresses | Produced by a model from the fetched pages only, then source-checked: each claim must arrive with a verbatim quote, and that quote must be found in the pages. A claim that fails is DELETED and counted in dropped_claims. |
Content-Security-Policy header. A CSP lists every host a site is permitted to contact, not one it uses — mining it yields a long, confident stack for tools the company has never touched.Sections and what each contains: Identity — Name, one-line description and industry, each traced to the page it was read from. Size signals — Headcount phrasing the company published about itself, plus a count of live job links. Tech stack — Technologies inferred from response headers and the assets the page actually loads. Funding & news — Funding and acquisition mentions from published articles, each with a dated quote. Contact surface — Emails, phones, postal addresses and social profiles found on the pages fetched.
Thin results & refunds
A dossier is thin when no page rendered at all, or when fewer than two of the nine signal groups resolved. A parked domain, a holding splash, a name registered and never used.
- On the credit rails, a thin dossier settles at
0and the whole reserve is refunded to the exact pools it came from. The row is stored withstatus: "refunded"so you can still see what was attempted. - On x402, a thin dossier returns
402 thin_resultand the payment is never settled. An on-chain payment has no refund path, so the check happens before the money moves. - A very SPARSE dossier is not thin. A local business with a name, a phone number and a stack is a real answer about a real company, and it bills.
Reading past dossiers
Free forever — these are reads of work you already paid for.
GET /api/dossiers?limit=20&domain=stripe.com
GET /api/dossiers/<id>
GET /api/credits # your spendable Ounie credits
GET /api/pricing # public: price, sections, x402 endpointMCP
A Streamable HTTP MCP server, plus legacy SSE. Works in Claude, Cursor, ChatGPT, the AI SDK and the Ounie AI Team.
Endpoint https://company.ounie.com/api/mcp
Legacy https://company.ounie.com/api/sse
Auth Authorization: Bearer cin_live_…
…or ?api_key=cin_live_… for hosts that can't set headers| Tool | Cost | What it does |
|---|---|---|
| build_company_dossier | 12 cr | Research a company from its domain. Thin refunds in full. |
| get_dossier | free | Re-read one you already built, by id. |
| list_dossiers | free | Your history, newest first, filterable by domain. |
| get_dossier_schema | free, public | The sections and the sourcing rules the output obeys. |
| get_credit_balance | free | Spendable Ounie credits. |
| get_pricing | free, public | Credit price and the x402 endpoint. |
| whoami | free | The authenticated key's owner and key id. |
x402 — keyless, pay per call
No account, no key. Pay $0.144 in USDC on Base. Two refusal gates protect the caller, and the order is deliberate.
POST https://company.ounie.com/api/x402/dossier
{"domain":"stripe.com"}
# Gate 1 — a request we can never serve is refused for FREE, before a quote:
# 400 invalid_request malformed domain, IP literal, port, private network
# 400 domain_unresolvable the name does not resolve
# 400 invalid_section unknown value in sections[]
# Otherwise: 402 with the terms
{ "x402Version": 1,
"accepts": [{ "scheme": "exact", "network": "base",
"maxAmountRequired": "144000",
"payTo": "0x…", "asset": "0x833589fCD…",
"extra": { "name": "USD Coin", "version": "2" } }] }
# Sign an EIP-3009 authorization and retry:
POST https://company.ounie.com/api/x402/dossier
X-Payment: <base64 payload>
# Gate 2 — verified, run, and only THEN settled. Nothing to sell:
# 402 thin_result your payment was NOT settlednetwork is the bare name base, not eip155:8453 — under x402 the naming scheme selects the protocol version, and this is a v1 offer. The extra block states the USDC EIP-712 domain so your signature does not revert on chain after the money is committed.Errors
| Status | Error | Meaning |
|---|---|---|
| 400 | domain_required | No domain or url in the body. |
| 400 | invalid_request | Malformed host, IP literal, non-standard port, credentials in the URL, or a host that resolves to a private network. |
| 400 | domain_unresolvable | The hostname does not resolve. Refused for free. |
| 400 | invalid_section | Unknown value in sections[]. |
| 401 | unauthorized | No usable cookie or bearer key. |
| 402 | insufficient_credits | Carries required_credits, balance_credits and buy_credits_url. Nothing was reserved. |
| 402 | thin_result | x402 only: nothing usable resolved, so the payment was not settled. |
| 429 | too_many_running | More than 5 dossiers in flight for one account. |
| 502 | dossier_failed | An upstream broke. You were refunded and not charged. |
| 503 | service_unavailable | Research is temporarily unavailable. Nothing was charged. |
Limits
| Limit | Value |
|---|---|
| Price | 12 credits per dossier · $0.144 USDC over x402 |
| Pages fetched | 5 per dossier (homepage + four candidates) |
| Concurrent dossiers | 5 per account |
| Active API keys | 5 per account |
| Recency window | 1825 days |
| Free forever | Reading, listing and exporting dossiers you already paid for |
Credits are shared across every Ounie app and bought at ounie.com.