# `POST /data/facts`

**Purpose:** Return structured facts for **one** filing by **`fact_id`**. For line-item-name queries (e.g. `revenue`, `net income`) use **[`POST /data/line-items`](/documents/post-dataline-items.md)** instead.

**Filing selection:** supply **`filing_id`**, or **`ticker`** and **`fiscal_year`** with optional **`form_type`** (default **`10-K`**) and **`quarter`**. Giving both, or `form_type` or `quarter` with `filing_id`, returns 422.

**Request:**

| Field | Type | Required | Notes |
|-------|------|----------|--------|
| `filing_id` | integer | Conditional | 1–10⁹. |
| `ticker` | string | Conditional | Required if `filing_id` omitted. 1–32 characters. |
| `form_type` | string | No | Default `10-K`, max 32. |
| `fiscal_year` | integer | Conditional | Required if `filing_id` omitted. 1990–2100. |
| `quarter` | string | No | Max 4 characters. |
| `fact_ids` | array of string | Yes | Non-empty; max **500** strings; each max **128** characters. |
| `detail` | string | No | Default `"full"`. `"light"` leaves out each result's `dimensional_breakdowns`. See [Response detail](/documents/responses.md#response-detail). |

**Response:**

| Field | Meaning |
|-------|---------|
| `ticker`, `form_type`, `fiscal_year`, `quarter` | Filing identity. |
| `source_url_prefix` | **Source-document URL base** for this filing on its regulator's platform (SEC viewer for US filings; DART, EDINET, filings.xbrl.org, cninfo for KR / JP / EU / CN). May be `null`. Join it with each fact's `source_locator` for the document URL. |
| `results` | Array of facts (each includes `concept`, `fact_id`, optional `source_locator`, values, units, period fields, plus `dimensions`, `dimensional_breakdowns` and `is_consolidated_total` — same meaning as in [`POST /data/line-items`](/documents/post-dataline-items.md)). `source_locator` may be `null` or a fragment / relative path (amendments may use a `../`-relative locator); callers concatenate it with `source_url_prefix` as-is. **Amendment-affected facts** also carry `restated: true` plus a `prior` object: for a value-**changed** fact `prior` holds the superseded value (`raw_value` / `calculated_value` / `unit` / `decimals` / `fact_id` / `source_locator`; `calculated_value` is the XBRL value as filed); for a fact **added** by the amendment `prior` is the sentinel `{ "added_by_amendment": "This fact was not present in the original filing; it was added by an amendment." }`. Both fields are always present; on original/unaffected facts they are `null`. |
| `credits_used` | `ceil(deduped_fact_id_count / 5) × 10`. |
| `amendment_context` | Optional; same idea as under filings when applicable. |
| `_warnings` | Optional strings (duplicate ids deduplicated, missing ids not found in the filing). |

**Errors:**

| HTTP | `error_code` | When |
|------|----------------|------|
| 400 | `DATA_FILING_QUARTER_REQUIRED` | Several filings match without a quarter; message lists available quarters. |
| 404 | `DATA_FILING_NOT_FOUND` | No filing for the given id or identity. |
| 403 | `PLAN_TIER_INSUFFICIENT_HISTORY`, `PLAN_TIER_INSUFFICIENT`, `PLAN_TIER_INSUFFICIENT_COVERAGE` | The filing is outside your plan (see [History truncation notice](/documents/coverage.md#history-truncation-notice), [Coverage scope notice](/documents/coverage.md#coverage-scope-notice)). Not charged. |
| 402 | `CREDITS_INSUFFICIENT` | Not enough credits. |
| 422 | — | Validation (empty fact_ids, limits, filing selector). |

**Example Request:**

```json
{
  "filing_id": 12345,
  "fact_ids": ["ix_1", "ix_2"]
}
```
