Construct a GET request to https://<org>.crm.dynamics.com/api/data/v9.2/<entitySetName> and append OData query options as URL query parameters.
Use $select to specify only the columns you need: $select=name,emailaddress1,statecode — omitting $select returns all fields and consumes unnecessary bandwidth.
Apply $filter to narrow results using OData predicate syntax: $filter=statecode eq 0 and contains(name,'Contoso') — Dataverse supports eq, ne, gt, lt, ge, le, and, or, not, startswith, endswith, contains.
Expand related records using $expand: $expand=parentaccountid($select=name,accountnumber) retrieves the parent account inline without a separate request.
Add $orderby and $top to control sort order and result count: $orderby=createdon desc&$top=50; use the @odata.nextLink in the response to fetch subsequent pages.
Request a total count by adding $count=true; the response includes an @odata.count property with the total matching records regardless of the page size.
Known gotchas
String comparisons in $filter are case-sensitive by default for some Dataverse field types; use the tolower() function when case-insensitive matching is required.
$expand on collection-valued navigation properties (one-to-many) is supported but nested $filter within $expand is limited — for complex cross-table filtering, consider FetchXML instead.
Dataverse enforces a maximum of 5,000 records per page by default; never assume a single response contains all matching records — always check for @odata.nextLink.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp