Skip to main content
Question

How do you know what a GI's OData column names and order will be?

  • August 31, 2026
  • 3 replies
  • 38 views

Forum|alt.badge.img

Note: A lot of this is written by Claude with directions from me. We ran into this issue while developing the MCP server.

The property list an exposed Generic Inquiry returns over OData is **neither the order
nor the exact set of columns you put in the Results Grid**, and I can't find anything in
the design tables that tells you what it *will* be. Asking in case I've missed it.

Say a GI's Results Grid holds three columns, in Sort Order: `Customer Name`,
`Order Nbr`, `Status`. What `$metadata` actually reports is something else:

- Any result column that is **also an entity key** is hoisted to the **front** of the list.
- Keys of the joined tables are **appended at the end even if you never added them** — this
  part *is* documented ("*GI Access Through OData: General Information*").
- Where two columns produce the same name, one becomes `X` and the other `X_2` — and which
  one keeps the bare name depends on **grid position**, not on the column.
- Inactive rows are skipped, and the order follows **Sort Order**, which is not Line Number.

So you can't read the grid and predict the output. And you can't recover it from the design
either:

- **`Caption` is only an override** and is NULL for most columns, so there's usually nothing
  to match on.
- **`SchemaField`** is NULL for most rows and DAC-qualified where present (`INTran.RefNbr`),
  so it never equals the bare property (`RefNbr`).
- The naming rule *is* documented — property names come from the field's **display name**,
  with invalid symbols stripped (*Preparation of an Inquiry for Exposure* → "Supporting the
  OData Specification"). But the display name isn't in `GIResult`: the `fieldName` field
  exists and is **virtual**, so it comes back NULL over OData. (Filtering it says so
  outright: *"Filter on '{0}' is not allowed because it is a virtual field."*)

Net effect: `$metadata` is the only source of truth, and any tool that needs to know *which
design column became which property* has to infer it positionally. That's uncomfortable for
two reasons. A wrong inference doesn't fail — it silently shifts every later column by one.
And because the `_2` suffix follows position, **editing a GI can move which column owns the
bare name**, which changes what an existing `$select=X` returns without any error.

Is the projection rule documented somewhere I've missed? If not, a paragraph in
"Supporting the OData Specification" stating where hoisted keys land, that ordering follows
Sort Order, that inactive rows are excluded, and how duplicate names are resolved would
remove the guesswork. Populating `GIResult.fieldName` would remove it entirely.

3 replies

Forum|alt.badge.img+5
  • Jr Varsity II
  • September 2, 2026

Hi ​@saratvemuri ,

The property list an exposed Generic Inquiry returns over OData is neither the order nor the exact set of columns you put in the Results Grid. Here is how Acumatica handles it:

1. The Key Fields Always Come First

Acumatica will automatically hoist any "Entity Keys" (the primary key fields of the tables included in your GI) to the very front of the OData field list. It does this regardless of where you positioned them in the GI Results Grid, or even if you included them in the Results Grid at all.

2. Field Names vs. Aliases

While you can assign a "friendly" header name or alias in the GI Results Grid, the OData feed often defaults to the underlying system field name or a generated alias (for example, outputting BranchID_2 instead of a custom label like "Company").

The Solution: How to know the exact schema

Because the output doesn't perfectly mirror your GI configuration, you cannot rely purely on the Results Grid to determine the final OData schema.

The definitive way to see the exact column names, data types, and order is to inspect the $metadata endpoint for your specific GI.

To do this, navigate to your OData URL in a web browser and append $metadata to the end:

https://<YourAcumaticaInstance>/odata/<TenantName>/<YourGIName>/$metadata

This will return an XML schema that explicitly defines every property and its type as it will be exposed by the OData service.

Hope above helps!!


Forum|alt.badge.img
  • Author
  • Freshman II
  • September 2, 2026

Thanks ​@Rakshanda

I understand that $metadata give the property names.  But It doesn’t tell me what those map to on the results grid.  You can usually pair them by eye, if you are human :-).   

I was using Claude to document GIs at scale (About 115 GIs) so that it helps with AI descriptions that then would make them more useful via MCP (This is the MCP4Acumatica project I built and is open source).  As good as models are these days, apparently it can’t always know that column acctCD came across as property EmployeeID.  So, documenting the projection i.e. how result grid maps to odata properties would be very helpful in this case.

Our solution for now is to explicitly set a name in the Caption field, which becomes the property name.  

Also, the above URL needs /t and /api and $metadata at service root can cover exposed GI at once:https://<instance>/t/<TenantName>/api/odata/gi/$metadata


Forum|alt.badge.img+5
  • Jr Varsity II
  • September 3, 2026

Hi ​@saratvemuri 

Thank you for sharing the updated OData URL structure

(https://<instance>/t/<TenantName>/api/odata/gi/$metadata)—retrieving the metadata for all exposed GIs at the service root is definitely much more efficient when documenting at scale!

Your workaround of explicitly setting the Caption field in the Results Grid is a great solution. Here's why that is the best approach for programmatic mapping:

When Acumatica generates the OData projection for a Generic Inquiry, it tries to derive the property name from the underlying Data Access Class (DAC) field (e.g., acctCD). If multiple tables have the same field name, or if it resolves it in a non-obvious way, the default mapping becomes unpredictable (as you saw with acctCD becoming EmployeeID).

By explicitly defining a Caption, you are overriding the default resolution logic. Acumatica respects the explicit Caption as the alias for the OData property name. This creates a hard, deterministic link between what you define in the GI and what is exposed in the API, eliminating the guesswork for an LLM (or any integration) trying to map the GI Results Grid back to the $metadata schema.

It sounds like your MCP4Acumatica project is doing some really interesting things by leveraging LLMs to interpret and document these inquiries. Forcing a 1:1 mapping via the Caption field is definitely the most robust way to give Claude (or any AI) the exact schema it needs to bridge that gap!