Skip to main content

Why this exists

LLMs hallucinate. Data brokers don’t show their work. BETA’s value isn’t just the data — it’s that every response carries provenance, and that BETA returns explicit non-answers when sources don’t back a claim. This page is the contract. If you build on BETA, you can rely on the shape and meaning of these fields. If a future version changes them, you’ll see the deprecation in the Changelog and have a migration window.

The grammar

Every response surfaces provenance through one or more of these fields:
FieldWhereMeaning
resolution.sourceevery endpointHow BETA matched your query: curated (registry hit) · discovered (LLM-discovered cache) · sec_fallback (ticker-only) · symbol_fallback (symbol + industry) · disambiguation (resolved an ambiguous name)
resolution.confidenceevery endpointConfidence in the entity match (01). Below 0.8 usually means a fallback / fuzzy match.
meta.sources[]/enrichWhich structured datasets contributed: entity_resolution, entity_summaries, material_events, company_mentioned_people, intelligence_snapshot, intelligence_history
[N] footnote markers in context/enrich synthesisArticle-source citations woven into the synthesized briefing prose
evidence[]/corroboratePer-claim evidence with type, text, date, confidence, change_type
sources_checked/corroborateWhich datasets BETA looked in — populated even when corroborated: false, so you know what was tried
meta.corroborated_at/corroborateISO timestamp of the corroboration run
meta.enrichedAt/enrichWhen this response was assembled (for cache decisions)
meta.coverage_note/peopleAlways present — explicit declaration of what the index covers and what it doesn’t

What BETA refuses to assert

Citation discipline means BETA tells you when it doesn’t know. The four canonical refusal shapes — these are real responses from the live API, not aspirational examples.

(a) Claim not backed by sources

/corroborate returns corroborated: false with reason: "no_match" when no SEC filings, news articles, or people-index records support the claim. This is not a failure — it is the signal.
{
  "entity": { "key": "anthropic", "name": "Anthropic", "verified": true },
  "results": [{
    "claim_index": 0,
    "corroborated": false,
    "confidence": 0,
    "reason": "no_match",
    "detail": "No SEC executive filings or news mentions match 'Nobody Famous' at this company. Note: BETA's people index covers SEC-level executives and news-mentioned individuals; mid-career roles may not appear.",
    "evidence": [],
    "sources_checked": [
      "sec_executive_changes",
      "company_mentioned_people"
    ]
  }],
  "meta": {
    "sources_available": [
      "entity_registry",
      "sec_executive_changes",
      "sec_ma_transactions",
      "company_mentioned_people",
      "source_articles"
    ],
    "entity_coverage": "private_company",
    "corroborated_at": "2026-05-20T03:52:00Z",
    "resolution": { "source": "curated", "confidence": 1 }
  }
}
Notice sources_checked is populated even on refusal — your audit trail shows what BETA tried.

(b) Company not in BETA’s database

/validate returns verified: false with message when the input is genuinely unknown.
{
  "verified": false,
  "confidence": 0,
  "entity": null,
  "message": "Company not found in database"
}

(c) Low-confidence fallback resolution

When BETA does match a query but the match comes from a fuzzy / fallback path, the resolution metadata says so explicitly. Don’t just check verified: true — read resolution.source and resolution.confidence.
{
  "verified": true,
  "confidence": 0.75,
  "entity": {
    "key": "block",
    "name": "Block, Inc.",
    "type": "sec_ticker_fallback",
    "ticker": "BSQKZ",
    "publicUrl": "https://getbeta.io/company/block"
  },
  "resolution": {
    "source": "sec_fallback",
    "confidence": 0.75
  }
}
resolution.source: "sec_fallback" means BETA matched on a SEC ticker, not via the curated registry. The 0.75 confidence is BETA’s way of saying “I have something, but I’m not certain it’s what you meant.” Downgrade trust accordingly — see Drop-in patterns below.

(d) Sparse people coverage

/people returns whatever it has, plus a meta.coverage_note that explicitly states what the index doesn’t cover.
{
  "entity": { "key": "anthropic", "name": "Anthropic" },
  "people": [],
  "meta": {
    "total_indexed": 15,
    "coverage_note": "People index covers SEC-filed executives, board members, and news-mentioned individuals. Mid-level roles are not indexed.",
    "resolution": { "source": "curated", "confidence": 1 }
  }
}
The empty people array combined with the coverage_note is BETA telling you: the company is real, the role type you asked about isn’t covered. That’s different from “this company doesn’t exist” or “we have no data.”

Drop-in patterns

How to wire BETA’s provenance into your system: 1. Downgrade displayed confidence when resolution.source isn’t curated:
function trustScore(resolution) {
  const base = resolution.confidence;
  if (resolution.source === 'curated') return base;
  if (resolution.source === 'discovered') return base * 0.85;
  return base * 0.6; // sec_fallback, symbol_fallback
}
2. Treat corroborated: false as ground truth:
const { results } = await corroborate(company, claims);
for (const r of results) {
  if (!r.corroborated) {
    // Don't assert this claim in your output.
    // Log r.detail. Optionally ask the user.
    continue;
  }
  // Use r.evidence as the citation when you cite the claim.
}
3. Surface meta.sources[] in your UI: Show users which structured datasets BETA consulted — it makes the response auditable and builds trust.
Based on: entity registry · SEC filings · 47 news articles
4. Use resolution.confidence < 0.8 as a human-review threshold: For high-stakes flows (legal, financial, compliance), route low-confidence resolutions to a human verification step rather than auto-acting.
if (response.resolution.confidence < 0.8 || response.resolution.source !== 'curated') {
  queueForHumanReview(response);
} else {
  proceedAutomatically(response);
}

Audit + freshness

  • Refresh cadence: Intelligence (SWOT, competitors, priorities) refreshes weekly per entity. Material events arrive within 24h of SEC filing.
  • Snapshot dates: meta.enrichedAt in /enrich and meta.corroborated_at in /corroborate tell you exactly how fresh the response is.
  • Stale detection: Compare the snapshot timestamp to today — > 14 days means BETA’s automated refresh missed this entity. Email hello@getbeta.io for a manual refresh.
  • Force-refresh: Currently internal-only. Programmatic force-refresh is on the Roadmap.

What we will never silently break

  • The field names and semantics in The grammar
  • The four refusal shapes in What BETA refuses to assert
  • The convention that corroborated: false is informational, not an error
  • The convention that an empty people array with a coverage_note is informational, not a failure
If we change these, you’ll see it announced in the Changelog with at least a 90-day migration window. The Citation Contract is the contract.