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

# SEC XBRL Financial Data

> Structured financial values from SEC XBRL filings — one line item over time, a company's full concept catalog, or one concept across all companies

Get the numbers, not the documents. `legal.v1.secXbrl()` wraps the SEC's XBRL APIs on `data.sec.gov` and returns normalized financial facts (net income, assets, shares outstanding, and so on) with a link back to the source filing. To find and read filings, use [SEC Filings](/legal-research/sec-filings) instead.

```bash title="Endpoint" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /legal/v1/sec-xbrl
```

| `type` | Use it to | SEC API wrapped |
| - | - | - |
| `concept` | Get one line item for one company over time | `/api/xbrl/companyconcept` |
| `facts` | List every concept a company reports, or pull several at once | `/api/xbrl/companyfacts` |
| `frames` | Compare one concept across all reporting companies for a period | `/api/xbrl/frames` |

## One line item over time (`concept`)

Provide exactly one of `cik` or `ticker`, a `tag`, and optionally a `taxonomy` (default `us-gaap`; also `ifrs-full`, `dei`, `srt`).

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST https://api.case.dev/legal/v1/sec-xbrl \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "concept",
      "ticker": "AAPL",
      "taxonomy": "us-gaap",
      "tag": "NetIncomeLoss",
      "formTypes": ["10-K"],
      "limit": 10
    }'
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  casedev legal:v1 sec-xbrl \
    --type concept \
    --ticker AAPL \
    --taxonomy us-gaap \
    --tag NetIncomeLoss \
    --form-type 10-K \
    --limit 10
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const result = await client.legal.v1.secXbrl({
    type: 'concept',
    ticker: 'AAPL',
    taxonomy: 'us-gaap',
    tag: 'NetIncomeLoss',
    formTypes: ['10-K'],
    limit: 10,
  })

  console.log(result.label)
  const fact = result.facts?.[0]
  if (fact) {
    console.log(fact.value, fact.end)
    console.log(fact.secUrl)
  }
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  result = client.legal.v1.sec_xbrl(
      type='concept',
      ticker='AAPL',
      taxonomy='us-gaap',
      tag='NetIncomeLoss',
      form_types=['10-K'],
      limit=10,
  )

  print(result.label)
  print(result.facts[0].value, result.facts[0].end)
  print(result.facts[0].sec_url)
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  result, _ := client.Legal.V1.SecXbrl(ctx, casedev.LegalV1SecXbrlParams{
      Type:      casedev.F(casedev.LegalV1SecXbrlParamsTypeConcept),
      Ticker:    casedev.F("AAPL"),
      Taxonomy:  casedev.F(casedev.LegalV1SecXbrlParamsTaxonomyUsGaap),
      Tag:       casedev.F("NetIncomeLoss"),
      FormTypes: casedev.F([]string{"10-K"}),
      Limit:     casedev.F(int64(10)),
  })
  ```
</CodeGroup>

Optional filters: `unit` (for example `USD`, `shares`, `USD/shares`), `formTypes`, `fiscalPeriods` (`FY`, `Q1`, `Q2`, `Q3`), and `dateAfter` / `dateBefore`, which filter on the fact's period end date.

## A company's concepts (`facts`)

Company fact payloads can be tens of MB for large filers, so `facts` has two modes:

* **Without `concepts`**, it returns a catalog only: each concept's taxonomy, tag, label, available units, fact count, and latest period end date. No values. Use `taxonomy` to narrow the catalog.
* **With `concepts`** (an array of `taxonomy:tag` strings, or bare tags that default to `us-gaap`), it returns normalized facts for just those concepts.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # Catalog
  curl -X POST https://api.case.dev/legal/v1/sec-xbrl \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "type": "facts", "ticker": "AAPL", "taxonomy": "us-gaap", "limit": 25 }'

  # Values for specific concepts
  curl -X POST https://api.case.dev/legal/v1/sec-xbrl \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "facts",
      "ticker": "AAPL",
      "concepts": ["NetIncomeLoss", "Assets"],
      "fiscalPeriods": ["FY"]
    }'
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # Catalog
  casedev legal:v1 sec-xbrl --type facts --ticker AAPL --taxonomy us-gaap --limit 25

  # Values for specific concepts
  casedev legal:v1 sec-xbrl \
    --type facts \
    --ticker AAPL \
    --concept NetIncomeLoss \
    --concept Assets \
    --fiscal-period FY
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const catalog = await client.legal.v1.secXbrl({
    type: 'facts',
    ticker: 'AAPL',
    taxonomy: 'us-gaap',
    limit: 25,
  })
  const concept = catalog.concepts?.[0]
  if (concept) console.log(concept.tag, concept.factCount)

  const values = await client.legal.v1.secXbrl({
    type: 'facts',
    ticker: 'AAPL',
    concepts: ['NetIncomeLoss', 'Assets'],
    fiscalPeriods: ['FY'],
  })
  const fact = values.facts?.[0]
  if (fact) console.log(fact.value)
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  catalog = client.legal.v1.sec_xbrl(
      type='facts',
      ticker='AAPL',
      taxonomy='us-gaap',
      limit=25,
  )
  print(catalog.concepts[0].tag, catalog.concepts[0].fact_count)

  values = client.legal.v1.sec_xbrl(
      type='facts',
      ticker='AAPL',
      concepts=['NetIncomeLoss', 'Assets'],
      fiscal_periods=['FY'],
  )
  print(values.facts[0].value)
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  catalog, _ := client.Legal.V1.SecXbrl(ctx, casedev.LegalV1SecXbrlParams{
      Type:     casedev.F(casedev.LegalV1SecXbrlParamsTypeFacts),
      Ticker:   casedev.F("AAPL"),
      Taxonomy: casedev.F(casedev.LegalV1SecXbrlParamsTaxonomyUsGaap),
      Limit:    casedev.F(int64(25)),
  })

  values, _ := client.Legal.V1.SecXbrl(ctx, casedev.LegalV1SecXbrlParams{
      Type:          casedev.F(casedev.LegalV1SecXbrlParamsTypeFacts),
      Ticker:        casedev.F("AAPL"),
      Concepts:      casedev.F([]string{"NetIncomeLoss", "Assets"}),
      FiscalPeriods: casedev.F([]casedev.LegalV1SecXbrlParamsFiscalPeriod{casedev.LegalV1SecXbrlParamsFiscalPeriodFy}),
  })
  ```
</CodeGroup>

## One concept across companies (`frames`)

`frames` returns one concept for every company that reported it in one calendar period. Provide `tag` and `period`; `taxonomy` defaults to `us-gaap` and `unit` to `USD`.

`period` must match `CY####`, `CY####Q#`, or `CY####Q#I`:

| Period | Meaning |
| - | - |
| `CY2024` | Annual duration |
| `CY2024Q1` | Quarterly duration |
| `CY2024Q1I` | Instantaneous point in time (balance sheet items) |

Callers pass ratio units as `USD/shares`; the endpoint converts them to the SEC's `USD-per-shares` form. Use `ciks` or `tickers` to restrict the results to a peer set (CLI: repeated `--peer-cik` or `--peer-ticker` flags), and `sort` (`value_desc` default, or `value_asc`).

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST https://api.case.dev/legal/v1/sec-xbrl \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "frames",
      "taxonomy": "us-gaap",
      "tag": "AccountsPayableCurrent",
      "unit": "USD",
      "period": "CY2019Q1I",
      "tickers": ["AAPL", "MSFT"],
      "sort": "value_desc",
      "limit": 10
    }'
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  casedev legal:v1 sec-xbrl \
    --type frames \
    --taxonomy us-gaap \
    --tag AccountsPayableCurrent \
    --unit USD \
    --period CY2019Q1I \
    --peer-ticker AAPL \
    --peer-ticker MSFT \
    --sort value_desc \
    --limit 10
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const result = await client.legal.v1.secXbrl({
    type: 'frames',
    taxonomy: 'us-gaap',
    tag: 'AccountsPayableCurrent',
    unit: 'USD',
    period: 'CY2019Q1I',
    tickers: ['AAPL', 'MSFT'],
    sort: 'value_desc',
    limit: 10,
  })

  console.log(result.total)
  const peer = result.data?.[0]
  if (peer) console.log(peer.entityName, peer.value, peer.loc)
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  result = client.legal.v1.sec_xbrl(
      type='frames',
      taxonomy='us-gaap',
      tag='AccountsPayableCurrent',
      unit='USD',
      period='CY2019Q1I',
      tickers=['AAPL', 'MSFT'],
      sort='value_desc',
      limit=10,
  )

  print(result.total)
  print(result.data[0].entity_name, result.data[0].value, result.data[0].loc)
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  result, _ := client.Legal.V1.SecXbrl(ctx, casedev.LegalV1SecXbrlParams{
      Type:     casedev.F(casedev.LegalV1SecXbrlParamsTypeFrames),
      Taxonomy: casedev.F(casedev.LegalV1SecXbrlParamsTaxonomyUsGaap),
      Tag:      casedev.F("AccountsPayableCurrent"),
      Unit:     casedev.F("USD"),
      Period:   casedev.F("CY2019Q1I"),
      Tickers:  casedev.F([]string{"AAPL", "MSFT"}),
      Sort:     casedev.F(casedev.LegalV1SecXbrlParamsSortValueDesc),
      Limit:    casedev.F(int64(10)),
  })
  ```
</CodeGroup>

## Response fields

Every fact row has the same shape:

* `taxonomy`, `tag`, `label`, `unit`: what was measured
* `value`: the reported number
* `start`: period start date; `null` for instantaneous facts
* `end`: period end date
* `fiscalYear`, `fiscalPeriod`, `form`, `filed`: the filing the fact came from (`null` on `frames` rows, which the SEC does not return these for)
* `accessionNumber`: SEC accession number of the filing
* `frame`: the SEC calendar frame (for example `CY2024Q1I`), `null` if not assigned
* `cik`, `entityName`: the reporting company
* `secUrl`: EDGAR filing index page for the source filing
* `loc`: reporting company location code (`frames` only)

Top level:

* `total`: rows matching before pagination
* `cik`, `ticker`, `entityName`: the resolved company (`concept` and `facts`)
* `label`, `description`: the concept's definition (`concept` and `frames`)
* `facts[]`: fact rows (`concept`, and `facts` when `concepts` is set)
* `concepts[]`: the catalog, with `taxonomy`, `tag`, `label`, `units`, `factCount`, `latestPeriodEnd` (`facts` without `concepts`)
* `data[]`: fact rows, one per reporting company (`frames`)

## Deduplication

A value is re-reported in later filings as a prior-period comparative, so the raw SEC data contains many duplicates of the same fact. With `dedupe: true` (the default) for `concept` and `facts`, only facts that carry a `frame` are returned. The `frame` is the SEC's own canonical assignment of one fact per calendar period, so this gives you one row per period. Set `dedupe: false` to get every reported fact, including comparatives. `frames` results are already one canonical fact per company.

## Notes

* Use `type: 'concept'` or `type: 'facts'` with a ticker or CIK; tickers resolve to CIKs automatically, as with SEC Filings.
* An unknown ticker returns `404` with code `TICKER_NOT_FOUND`. A company with no XBRL data, or that does not report the requested concept, frame, or unit, returns `404` with code `XBRL_NOT_FOUND` and a message naming the CIK and concept. An invalid `period`, `unit`, or `taxonomy` returns `400`.
* `limit` is capped at `100` and `offset` uses standard offset pagination.
* Company data is cached for up to 15 minutes, since `data.sec.gov` updates throughout the day. Frames for closed periods are cached for up to 24 hours. Filters are applied after the fetch, so repeated queries are fast.
* SEC rate limits are shared with the SEC Filings endpoint.
* This endpoint is free and uses only SEC-operated infrastructure.

## Coverage and batch behavior

The SEC XBRL APIs aggregate standard-taxonomy facts that apply to the whole filing entity. Custom-taxonomy and segment facts are outside this API. Use `sec-filing` for company metadata and filing documents. These endpoints retrieve public data; submission of Form D or other filings is a separate EDGAR workflow.

A selected-concepts `facts` request is all-or-nothing: if any requested concept is missing, the response is `404 XBRL_NOT_FOUND` listing every missing concept. Query the catalog first when assembling a company's concept list.

Array filters must contain non-empty strings, including CIKs (for example, `"320193"`). Invalid entries and impossible calendar dates return `400 VALIDATION_ERROR`.

Raw SEC payloads are cached per process with a 20 MiB estimated parsed-memory budget and at most 12 entries. Oversized responses are served without retention; least recently used entries are evicted to make room. The budget estimates object and string storage rather than guaranteeing the worker's total heap usage.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.