---
title: "Compare N entities × M metrics at one fiscal period — premium"
method: POST
path: "/api/v1/compare"
tags: ["Compare"]
---

# Compare N entities × M metrics at one fiscal period — premium

`POST /api/v1/compare`

## Request

- Base URL: `https://api.hub-equity.com`
- URL: `https://api.hub-equity.com/api/v1/compare`
- Auth: HTTP bearer

Single round-trip comparison matrix with calendar-year fiscal alignment. Returns one row per entity with metadata (sector, country, auditor) + a `cells` map keyed by `hub_concept_code` → CompareCell {value, currency, period_start, period_end, fiscal_year, source filing}.

Periods are matched on the CALENDAR year of `period_end` (`period_alignment = calendar_year`), not on each issuer's fiscal year: for an issuer that does not close in December the value can differ from `/api/v1/entities/{id}/financials` for the same year, and `fiscal_year` on each cell says which fiscal year was served. A missing key means no consolidated value with a `period_end` in that calendar year: the issuer did not report it, or (52/53-week issuers closing in early January) its fiscal year closed in the next calendar year.

Caps 10×10. Consolidated values only (segment rows excluded), one value per (entity, concept).

## Request body

- CompareRequest: Request body for POST /api/v1/compare.
  - `entity_ids` string[], required: Entities to compare (max 10): UUID, ticker or `TICKER.MIC`, as on every `/entities/{id}` route. An unknown identifier answers 404, an ambiguous ticker 409.
  - `hub_concept_codes` string[], required: Hub-Equity standardized concept codes (max 10), e.g. ['REVENUE', 'NET_INCOME', 'TOTAL_ASSETS'].
  - `fiscal_year` integer, required: Calendar year — for each issuer we pick the FY whose period_end falls in that year (Bloomberg / FactSet convention). Example : `fiscal_year=2024` returns AAPL's FY ending Sep 2024, MSFT's FY ending Jun 2024, LVMH's FY ending Dec 2024.
  - `fiscal_period_type` 'FY' | 'Q1' | 'Q2' | 'Q3' | 'Q4' | 'H1' | 'H2': Fiscal period type. Default 'FY' (full year). Other values are accepted for forward compatibility but currently force-overridden to 'FY' with a note in the response, since quarterly periods are not calendar-comparable across issuers (Apple Q1 ends Dec, MSFT Q1 ends Sep).

## Response `200`

Comparison matrix

- ApiResponseCompareEntitiesResult
  - `success` boolean, required
  - `data` CompareEntitiesResult
    - `fiscal_year` integer, required
    - `fiscal_period_type` string, required
    - `rows` CompareRow[], required
      - `entity_id` string, required
      - `name` string, required
      - `ticker` string, nullable
      - `country` string, nullable
      - `sector` string, nullable
      - `gics_sector` string, nullable
      - `auditor_name` string, nullable
      - `cells` object, required: Map hub_concept_code → CompareCell. Missing key = no fact for that pair.
    - `notes` string[]
    - `period_alignment` string: How rows were aligned across issuers. 'calendar_year': a cell is the row whose period_end falls in [YYYY-01-01, YYYY-12-31], so a non-December filer may be shown a different fiscal year than the one its own annual report labels. Compare period_start / period_end / fiscal_year on each cell to see the span actually served.
  - `error` ApiError: API error details.
    - `code` string, required
    - `message` string, required
    - `details` object, nullable
  - `meta` ApiMeta: API response metadata. Pagination fields (``page`` / ``per_page`` / ``total``) are populated on collection endpoints only. They are omitted from the payload on single-resource endpoints.
    - `timestamp` string, date-time
    - `request_id` string, nullable
    - `page` integer, nullable
    - `per_page` integer, nullable
    - `total` integer, nullable
  - `links` ApiLinks: HATEOAS-style pagination cursors. Host-relative path + query links for a collection page. Present on collection endpoints, ``null`` fields where a page doesn't exist (``next`` on the last page, ``prev`` on the first). The whole ``links`` object is omitted from single-resource responses (see ``ApiResponse`` serializer).
    - `self` string, nullable
    - `first` string, nullable
    - `prev` string, nullable
    - `next` string, nullable
    - `last` string, nullable

## Other responses

- `401`: AUTH_REQUIRED — anon or no Authorization header
- `403`: SCOPE_MISSING — Free key, requires Pro/Enterprise
- `422`: Pydantic validation error (cap exceeded, empty arrays, etc.)

---

[API](https://skmtc.dev/hub-equity/apis/hub-equity-api.md) · [All operations](https://skmtc.dev/hub-equity/apis/hub-equity-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hub-equity/apis/hub-equity-api/revisions/e8eeda5dc13e?raw)
