---
title: "Get Legacy Report Field Map"
method: GET
path: "/api/v1/custom-reports/legacy-field-map"
tags: ["Custom Reports", "Public API"]
---

# Get Legacy Report Field Map

`GET /api/v1/custom-reports/legacy-field-map`

## Request

- Base URL: `https://companySubDomain.bamboohr.com`
- URL: `https://companySubDomain.bamboohr.com/api/v1/custom-reports/legacy-field-map`
- Auth: OAuth 2
  - Authorization code: `/authorize.php`
  - Token URL: `/token.php` scopes: `report`
- TypeScript: <https://skmtc.dev/bamboohr/apis/bamboohr-api/docs/api/v1/custom-reports/legacy-field-map/get.ts> (a function with typed inputs; its response is checked against the schema)

Returns the mapping from the field identifiers the deprecated Reports > Get Company Report (`get-company-report`) endpoint emitted to the field names the Custom Reports and Datasets endpoints use today. Use it to repoint automations that still reference legacy identifiers — a field that came back as `location` before the report migration is `jobInformationLocation` afterward. To translate legacy report IDs rather than field identifiers, use Get Legacy Report ID Map (`get-legacy-report-id-map`) instead.

The map covers the whole company and is not paginated. It is not scoped to the calling user's reports or field permissions, so a field appearing here does not mean the caller can read its data.

A legacy identifier can map to more than one field. The legacy report emitted an amount column and its currency-code column under a single identifier, so `payRate` maps to both `compensationPayRate` and `compensationPayRateCurrencyCode`. The identifier alone cannot tell you which one a given report used, so compare `type` or `fieldLabel` against the column you are replacing. An identifier that is absent from the response has no equivalent field at all — that column was lost in the migration, and there is nothing to point an automation at.

Some legacy fields encoded a category in the field itself: a legacy "Vacation" time off field returned only vacation hours. These map to a general field plus a `qualifier`, and you have to apply it. If you request the mapped `fieldName` on its own, you get every category rather than the one the legacy field returned. The operator differs by field — time off policy qualifiers use `equal`, while time off category, benefit plan, and training qualifiers use `includes` and expect the value wrapped in an array. To reproduce a legacy "Safety Training" due-date column, request `trainingDueDate` and filter `{"field": "trainingName", "operator": "includes", "value": ["Safety Training"]}`.

Qualifier values are legacy names carried over without validation, so a category, plan, or training that has since been renamed or removed will produce a qualifier that matches nothing. Check the value against Datasets > Get Field Options (v1.2) (`get-field-options-v1_2`) before repointing an automation.

The map is cached per account for up to an hour, so a field that was just added or renamed may not appear immediately.

OAuth Scopes: report

## Response `200`

Returns an object containing a single `mappings` array, with one entry per legacy-identifier-to-field mapping in the account.

- object
  - `mappings` object[]
    - `legacyFieldId` string: Identifier the legacy report API emitted for this field: an api alias such as `location`, or `<fieldId>` / `<fieldId>.<subfieldId>` when the field had no alias. Numeric ids may be negative — calculated columns such as full name or length of service carry a negative id — so match them as signed integers, not as digits only.
    - `fieldName` string: Field name this legacy identifier now maps to. Matches the key the report and dataset endpoints use in their responses, so it can be used as-is.
    - `fieldLabel` string, nullable: Human-readable label of the semantic field. Always null on time off, benefit, and training entries.
    - `type` string, nullable: Semantic field type, for example `text` or `options`. Always null on time off, benefit, and training entries.
    - `entityName` string, nullable: Semantic entity the field belongs to, for example `jobInformation`. Always null on time off, benefit, and training entries.
    - `qualifier` object, nullable: Filter required to scope the mapped field the way the legacy field was scoped. Null when no filter is needed, including the `completedTraining` entries — that legacy column was never scoped to a single training.
      - `fieldName` string: Field to filter on, in the same field-name vocabulary as `fieldName`. Which field this is depends on the legacy field's group — time off entries qualify on `timeOffCategory` or `timeOffPolicyName`, benefit entries on `benefitPlanName`, training entries on `trainingName`.
      - `operator` 'includes' | 'equal': Filter operator to apply. `includes` expects the value wrapped in an array; `equal` expects it as-is. This is not uniform across qualifier fields, so use the value given here rather than assuming one. In OData-style filter strings the equivalents are `in ('value')` and `eq 'value'`.
      - `value` string: Value to filter that field to, taken from the legacy field's name and not validated against the values the qualifier field currently accepts. Always a plain string, including when `operator` is `includes` — wrap it in an array yourself for that operator.

## Other responses

- `401`: Unauthorized. No response body is returned.
- `403`: The authenticated user is not authorized to access reports.
- `500`: Internal server error.

## Changes

- **2026-11-03** `922fc15f43a7`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/bamboohr/apis/bamboohr-api/changes/api/v1/custom-reports/legacy-field-map/get.md)

---

[API](https://skmtc.dev/bamboohr/apis/bamboohr-api.md) - [All operations](https://skmtc.dev/bamboohr/apis/bamboohr-api/llms.txt) - [OpenAPI document](https://skmtc.dev/bamboohr/apis/bamboohr-api/revisions/922fc15f43a7?raw)
