> ## Documentation Index
> Fetch the complete documentation index at: https://developers.getbeta.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Citation Contract

> How BETA documents its sources — and what BETA refuses to assert.

## 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](/changelog) and have a migration window.

## The grammar

Every response surfaces provenance through one or more of these fields:

| Field                               | Where               | Meaning                                                                                                                                                                                                            |
| ----------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `resolution.source`                 | every endpoint      | How 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.confidence`             | every endpoint      | Confidence in the entity match (`0`–`1`). Below `0.8` usually means a fallback / fuzzy match.                                                                                                                      |
| `meta.sources[]`                    | `/enrich`           | Which structured datasets contributed: `entity_resolution`, `entity_summaries`, `material_events`, `company_mentioned_people`, `intelligence_snapshot`, `intelligence_history`                                     |
| `[N]` footnote markers in `context` | `/enrich` synthesis | Article-source citations woven into the synthesized briefing prose                                                                                                                                                 |
| `evidence[]`                        | `/corroborate`      | Per-claim evidence with `type`, `text`, `date`, `confidence`, `change_type`                                                                                                                                        |
| `sources_checked`                   | `/corroborate`      | Which datasets BETA looked in — populated **even when `corroborated: false`**, so you know what was tried                                                                                                          |
| `meta.corroborated_at`              | `/corroborate`      | ISO timestamp of the corroboration run                                                                                                                                                                             |
| `meta.enrichedAt`                   | `/enrich`           | When this response was assembled (for cache decisions)                                                                                                                                                             |
| `meta.coverage_note`                | `/people`           | Always 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.**

```json theme={null}
{
  "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.

```json theme={null}
{
  "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`.**

```json theme={null}
{
  "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](#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.

```json theme={null}
{
  "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`:**

```javascript theme={null}
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:**

```javascript theme={null}
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.

```text theme={null}
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.

```javascript theme={null}
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](mailto:hello@getbeta.io)** for a manual refresh.
* **Force-refresh**: Currently internal-only. Programmatic force-refresh is on the [Roadmap](/roadmap).

## What we will never silently break

* The field names and semantics in [The grammar](#the-grammar)
* The four refusal shapes in [What BETA refuses to assert](#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](/changelog) with at least a 90-day migration window. The Citation Contract is the contract.
