Query company-level financial metrics (Revenue, EBITDA, Net Debt, multiples, etc.) with filtering and currency conversion.
Custom fields are not metrics. A custom field is a client-defined attribute on an entity (e.g. "Deal Type", "Client Industry") — distinct from a custom *metric*, which is a client-defined metric definition and is served by this tool. The test is whether the name is a specific line item or a topic: "EBITDA", "Adjusted Revenue", and "Cloud Services revenue" are line items this tool serves, while "revenue drivers", "key initiatives", "recent events", and "business update" describe a topic and are custom fields until custom-field-search says otherwise, however financial the wording. This tool cannot answer a topic phrase, whether the question is a plain lookup ("what is X for Acme?") or an aggregate ("average X across the portfolio", "group by X"), and line items that happen to relate to the topic are not an answer to it. Call custom-field-search first; only treat the name as a metric once that returns no match. This takes precedence over any instruction to resolve an unfamiliar name through metric-definition-search — check the fields first. If metric-definition-search has already returned close matches for the name, present them rather than asking whether the name is a custom field; ask the user only when neither search matches.
Before querying: Always call with help: true and the same filter.companyIds first. Use only metric types returned for each company. Never query metrics for company IDs without calling help first.
Required steps: 1. Use the entity-search tool to find company IDs by name. 2. Call this tool with help: true and filter: { companyIds: [...] }. 3. Only then call with a metric query.
Use this tool for questions like:
- "What is the latest quarterly Revenue for company ID 123?"
- "Give me Revenue for these company IDs: [1, 5, 10]"
Pagination:
- Results are paginated (100 per page). Check pagination.hasNextPage and pagination.totalCount in the response.
- Decide whether to fetch more pages based on your analysis needs:
- Compare totalCount vs returnedCount to see how much data remains
- If querying N companies and need data for all of them, you may need to paginate (results may have multiple rows per company)
- For exploration, sampling, or when a subset is acceptable, the first page may suffice
- To fetch more: call with the SAME query parameters plus pagination.after set to pagination.nextCursor
- When unsure if complete data is needed, ask the user before fetching many pages
Important:
- You MUST call with help: true first whenever you have new or unfamiliar company IDs. Never call this tool for a metrics query without having called help with those company IDs first.
- When company IDs are provided, metric type resolution is automatically filtered to only those companies, preventing false positives from other companies' metric types.
Using date='latest':
- Results are ordered by date descending (most recent first)
- The FIRST occurrence of each unique (company.id, metric_definition_set_item_id, period, scenario) combination is the latest value for that group
Standard Metrics vs Custom Metrics:
- When company IDs are provided, the help response returns ALL metrics for those companies in one list which are both: standard metrics (metric_type is set) and custom metrics (metric_type: null, metric_definition_id is set).
- Use metric.metricType for standard metric types when available (preferred).
- Use metric.metricDefinitionId when the item has its metric_type: null, at this point the metric_definition_id in that item is the direct query key, no metric-definition-search needed.
- When no company IDs are provided, the response only includes standard metric types. In the case that you need a custom metric by name, use the metric-definition-search tool to find its metric_definition_id.
- If a metric name doesn't match a standard metric type, you must use the metric-definition-search tool to find the metric definition ID, then call this tool again with metric.metricDefinitionId set to the numeric ID.
- Exactly one of metric.metricType or metric.metricDefinitionId must be provided.
REQUIRED WORKFLOW FOR METRIC QUERIES: 1. ALWAYS call with help=true FIRST (with filter.companyIds if applicable) 2. Check if the user's requested metric matches any metric_type in the help response 3. If found (metric_type is not null) -> use metric.metricType with the matching standard type 4. If NOT found as a standard type, check for custom metrics (metric_type: null) in the help response:
- If company IDs were provided: look for an item where labeled_as matches the requested metric name and use its metric_definition_id directly with metric.metricDefinitionId
- If no company IDs were provided: use the metric-definition-search tool with the metric name to get the metric_definition_id, then call company-metrics with that metricDefinitionId
5. If still NOT found -> only then attempt to derive/calculate from available data 6. NEVER skip steps 1-4 and go straight to calculation or assumptions
metric_type vs labeled_as: metric_type is the API key for standard metrics (e.g. "Profit"). For custom metrics, metric_type is null, in which case you should use metric_definition_id as the API key instead. Both standard and custom metrics include labeled_as as the display name (e.g. "Adjt/ EBITDA"), which can differ per company. Always use labeled_as when describing results to users, never metric_type or metric_definition_id.
Periods define what is collected on an ongoing basis:
- Trailing Period: Represents metrics that are measured over a period of time (e.g., Revenue). Includes Month, Quarter, Semiannual, Last Twelve Months (LTM) and Year to Date (YTD) periods.
- Point in Time: Measure for data points that are reported as of a certain date (e.g., Total Debt). Includes the "As Of" period.
Fiscal Year-End:
- When you call help with company IDs, each company in the help response includes fiscal_year_end (e.g., 'December 31', 'March 31'). Use the date parameter with specific fiscal year-end dates rather than 'latest' for accurate YoY comparisons. If null, assume calendar year (December 31).
When period is set to "Quarter", "Semiannual", "LTM", or "YTD", the date field represents the END date of that period. For example:
- period="Quarter" with date="2024-12-31" returns the 3-month period ending December 31, 2024 (Oct-Nov-Dec)
- period="LTM" with date="2024-12-31" returns the 12-month period ending December 31, 2024
- These are TRAILING periods from the specified date. Each data point has a date that represents the PERIOD END DATE. Multiple dates will be returned because each represents a different rolling period window.
Version Dates (versionDates):
- IMPORTANT: versionDates is a field inside the metric object — always pass it as metric.versionDates, NOT at the root query level.
- Use versionDates whenever the user uses ANY time-relative phrase: "last week", "last month", "a month ago", "yesterday", "before", "what did we have on [date]". Calculate the actual YYYY-MM-DD date and pass it in the array.
- IMPORTANT: date controls WHICH metric period row to return (e.g. Dec 2025). versionDates controls what the value was recorded as on a given calendar date. They are independent — do NOT use date to answer past-value questions.
- Optional array of YYYY-MM-DD dates (max 7). Each date adds a field value_on_YYYY_MM_DD to every result node.
- Example: metric.versionDates: ["2026-04-01", "2026-04-30"] adds value_on_2026_04_01 and value_on_2026_04_30 to each node.
- Each field reflects the metric value as recorded in the audit log on or before that date, excluding changes made after it.
- Always in the original reporting currency — there is no FX equivalent. Omit currency when using versionDates for value change comparison so all fields are in the same currency.
- Use cases:
- Point-in-time: "What was Revenue last week?" → metric.versionDates: ["<date 7 days ago>"], show only versioned field
- Value change detection: "Did Revenue change since Monday?" → metric.versionDates: ["<monday>"] + value; rows where they differ changed
- Changes throughout a week: metric.versionDates: ["<mon>", "<tue>", "<wed>", "<thu>", "<fri>"] — compare adjacent fields to find when the shift occurred
- When to use value vs versioned fields: for value change detection present value (current) alongside the versioned field. For point-in-time or cross-date comparisons, use only the versioned fields — do NOT present value to the user as it is today's live value and is not relevant.
- Not available for calculated or imported metrics — the aliased fields will be null for those rows.
Grouped Aggregation (aggregation):
- Use
aggregation: { groupByFieldDefId, groupByFieldDate? } to get metric totals grouped by a custom field's values (e.g. "total Revenue by Client Industry") instead of per-row detail — the database computes one row per field value: { group, metricRowCount, sum, average }.
- Use the custom-field-search tool first (with
field_type: 'Company') to resolve the field name to its groupByFieldDefId.
groupByFieldDate (YYYY-MM-DD) is required only when the field being grouped by is itself a dated (time-series) custom field; omit it otherwise.
- Scope: provide
filter.companyIds to aggregate specific companies, or omit filter entirely to deliberately aggregate across the whole portfolio ("across my portfolio"). Never pass an empty companyIds list to mean "all" — it is rejected, since an empty list usually means entity-search found no matches.
- Hard rule:
metric.date must be an explicit single YYYY-MM-DD date. 'latest', 'earliest', and omitting metric.date are all rejected — grouped aggregates sum every matching row, so the period must be pinned to avoid silently mixing periods into one total.
metric.versionDates cannot be combined with aggregation — it targets per-row audit history, not aggregate totals.
- For monetary metrics, sum and average are converted to one currency before summing (each row via
value_fx), so a group spanning companies with different reporting currencies is a real total, not a blend. Pass currency to choose it (ISO 4217 code); defaults to USD if omitted. The response's currency field reports which one was used — always state it alongside the numbers. Non-monetary metrics (percent, number, ratio, ...) are unaffected by currency, and the response omits the field.
pagination is ignored when aggregation is provided; grouped responses are not paginated.
Source Citations:
- Each result row may include a
document_tags object (PDF sources, grouped by field name) or an excel_tag object (spreadsheet source), but never both — when a metric was tagged in both a PDF and a spreadsheet, only the active (most recently updated) source is surfaced. The object is only present when annotations exist for that row.
- PDF citation entries provide
filename, page, and document_id.
- Excel:
excel_tag is the citation object itself, providing filename, sheet_name, cell (an A1 reference, e.g. "AW12"), and document_id.
- When presenting values to the user, cite the source alongside the relevant value so the user can verify the data against its source.
- For PDFs: cite filename and page number.
- For Excel: cite filename, sheet name, and the
cell reference (e.g. "A1").
- If multiple values share the same source, a single citation after the group is sufficient.