---
title: "Run one bounded query against a declared financial dataset."
method: POST
path: "/v1/data/query"
---

# Run one bounded query against a declared financial dataset.

`POST /v1/data/query`

## Request

- Base URL: `https://api.candor.money`
- URL: `https://api.candor.money/v1/data/query`
- Auth: HTTP bearer

Run one bounded query against a declared financial dataset. Inspect the selected dataset schema for accepted filters and defaults; omitting filters uses those defaults. Cursor-paginated results keep records, calculations, and pagination under data.page. Calculations cover exactly the returned records, not later pages or the full workspace. Follow next_actions for the exact continuation, preserving the query filters.

## Headers

- `Idempotency-Key` string, required

## Request body

- union
  - PropertiesDatasetQueryRequest: Query tracked properties and their selected dated estimates.
    - `dataset` 'properties', required: Which declared dataset to query. `candor data list` names them.
    - `filters` CursorDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
  - AccountsDatasetQueryRequest: Query the accounts dataset.
    - `dataset` 'accounts', required: Which declared dataset to query. `candor data list` names them.
    - `filters` CursorDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
  - BalancesDatasetQueryRequest: Query the balances dataset.
    - `dataset` 'balances', required: Which declared dataset to query. `candor data list` names them.
    - `filters` CursorDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
  - AccountTermsDatasetQueryRequest: Query the effective account terms dataset.
    - `dataset` 'account_terms', required: Which declared dataset to query. `candor data list` names them.
    - `filters` AccountTermsDatasetQueryFilters: Account terms reload revisions, assertions, and coverage per account, so their page ceiling stays at 100.
      - `account_identity_id` string: Restrict history caps to one durable account identity.
      - `cursor` string: Omit for the first page. Continue with the exact next_actions entry from the preceding account-terms response, preserving the account filter.
      - `limit` integer
  - TransactionsDatasetQueryRequest
    - `dataset` 'transactions', required: Which declared dataset to query. `candor data list` names them.
    - `filters` TransactionDatasetQueryFilters
      - `cashflow_role` 'income' | 'expense' | 'transfer' | 'debt_payment' | 'refund' | 'unknown': Keep only records with this effective cashflow role. expense is what counts as spending and income as earnings; transfer and debt_payment move money between the user's own accounts or settle a card. Omit for every role.
      - `category` string: Case-insensitive exact category match after splits, corrections, rules, and source fallback. Use uncategorized for unresolved transactions. Omit this filter to return transactions across all categories.
      - `cursor` string: Omit for the first page. Continue with the exact next_actions entry from the preceding response, preserving the query filters.
      - `limit` integer: Maximum transactions in this page, default 50. A larger limit does not imply complete history; check pagination and follow next_actions.
      - `merchant` string: Case-insensitive substring match across the effective label, raw merchant name, and transaction description. Omit this filter to return transactions across all merchants.
      - `since` string: Inclusive first transaction date, YYYY-MM-DD. Omit for no lower date bound.
      - `source_account_id` string: Restrict transactions to one visible account using the exact id returned by accounts.list. Omit this filter to return transactions across every visible account.
      - `tag` string: Keep only transactions carrying this tag (rules.create add_tag), matched without regard to case; the transactions a tagged goal reads. Omit for every transaction.
      - `changed_after` string: Exclusive change timestamp in UTC ISO-8601 format. Includes late arrivals, edits, and removals regardless of posting date. Use the opening delta bounds for a checkpoint sweep.
      - `changed_through` string: Inclusive change timestamp in UTC ISO-8601 format. Requires changed_after; omitted upper bound is fixed when the read starts and preserved by next_actions. Rows are current records, not historical versions.
      - `category_provenance` string: Filter category provenance: rule (including splits), canonical, source_fallback, unclassified, or source_only_or_missing. Source-only does not mean a user decision is required.
      - `unmatched` boolean: true returns only transactions no rule or correction has reached and no split allocates. Their category, when present, is the source provider's fallback. The page's calculations add label_counts, grouped by merchant (a row's merchant_name, else its label) the way merchant_name_contains matches, so one rule per entry covers the most rows. Without since, until, changed_after, or a cursor, the read covers records changed after the workspace's last acknowledged opening and says so in an unmatched_window_defaulted warning with a full-sweep continuation; before any acknowledged opening it covers every record. Pass since or changed_after to choose the window yourself.
      - `until` string: Inclusive last transaction date, YYYY-MM-DD. Omit for no upper date bound.
  - CoverageDatasetQueryRequest
    - `dataset` 'coverage', required: Which declared dataset to query. `candor data list` names them.
    - `filters` EmptyDatasetQueryFilters
  - RecurringDatasetQueryRequest: Query the recurring dataset.
    - `dataset` 'recurring', required: Which declared dataset to query. `candor data list` names them.
    - `filters` RecurringDatasetQueryFilters: The recurring list is bounded. Follow its data.query continuation to page through omitted records; the recurring dataset supports cursor pagination.
      - `cursor` string: Continue the recurring dataset scan with the exact next_actions filters.
      - `account_identity_id` string: Return only series posting to this account identity.
      - `cashflow_role` 'income' | 'expense' | 'transfer' | 'debt_payment' | 'refund' | 'unknown': Effective cashflow role of the series. Use expense for bills and subscriptions; transfer and debt_payment series move money between the user's own accounts or settle a card. Rows promoted before the role was persisted carry none and are left out of a filtered read.
      - `direction` 'inflow' | 'outflow' | 'neutral': Whether the series is money out or money in.
      - `due_within` integer: Only series expected within this many days of today, overdue included.
      - `status` string: Comma-separated statuses: candidate, active, stopped, dismissed. Omit for active and candidate.
      - `limit` integer
  - HoldingsDatasetQueryRequest: Query the holdings dataset.
    - `dataset` 'holdings', required: Which declared dataset to query. `candor data list` names them.
    - `filters` HoldingsDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
      - `source_account_id` string: Restrict positions to one visible source account.
  - HoldingValuationsDatasetQueryRequest: Query the holding valuations dataset, one record per holding per day from the nightly valuation.
    - `dataset` 'holding_valuations', required: Which declared dataset to query. `candor data list` names them.
    - `filters` HoldingValuationsDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `holding_id` string: Restrict the daily records to one holding.
      - `limit` integer
      - `since` string: Earliest day (YYYY-MM-DD) to include.
      - `source_account_id` string: Restrict the daily records to one visible source account.
      - `until` string: Latest day (YYYY-MM-DD) to include.
  - InvestmentTransactionsDatasetQueryRequest: Query the investment transactions dataset.
    - `dataset` 'investment_transactions', required: Which declared dataset to query. `candor data list` names them.
    - `filters` CursorDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
  - BudgetsDatasetQueryRequest
    - `dataset` 'budgets', required: Which declared dataset to query. `candor data list` names them.
    - `filters` BudgetDatasetQueryFilters
      - `limit` integer
      - `period` string: The window this covers.
  - GoalsDatasetQueryRequest: Query the goals dataset.
    - `dataset` 'goals', required: Which declared dataset to query. `candor data list` names them.
    - `filters` object: Goals come back enriched with their current version, latest outcome, and progress history, so their page ceiling stays at 100.
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
  - RulesDatasetQueryRequest: Query the rules dataset.
    - `dataset` 'rules', required: Which declared dataset to query. `candor data list` names them.
    - `filters` object: Rules are projected through their basis transactions for visibility, so their page ceiling stays at 100.
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
  - CategoriesDatasetQueryRequest: Query the categories dataset.
    - `dataset` 'categories', required: Which declared dataset to query. `candor data list` names them.
    - `filters` CategoriesDatasetQueryFilters
      - `limit` integer: Posted records to read before aggregating; the coverage block says whether the window was read completely.
      - `since` string: First posted day to read, YYYY-MM-DD. Defaults to three months before today.
      - `until` string: Last posted day to read, YYYY-MM-DD. Defaults to today.
  - CashflowDatasetQueryRequest: Read income, spending, and the largest spending categories for every month of a window, the whole recorded history at a glance.
    - `dataset` 'cashflow', required: Which declared dataset to query. `candor data list` names them.
    - `filters` CashflowDatasetQueryFilters
      - `since` string: First posted day to read, YYYY-MM-DD. Defaults to the first day of the month 23 months before until, so the read covers 24 calendar months. A window spans at most 36 months.
      - `until` string: Last posted day to read, YYYY-MM-DD. Defaults to today.
  - ChangesDatasetQueryRequest
    - `dataset` 'changes', required: Which declared dataset to query. `candor data list` names them.
    - `filters` ChangesDatasetQueryFilters
      - `account_identity_id` string
      - `domain` 'all' | 'spending' | 'income' | 'recurring' | 'account_terms' | 'investments'
      - `limit` integer
      - `since` string: Inclusive comparison range date (YYYY-MM-DD); supply all four date fields for spending and income.
      - `until` string: Inclusive comparison range date (YYYY-MM-DD); supply all four date fields for spending and income.
      - `comparison_since` string: Inclusive comparison range date (YYYY-MM-DD); supply all four date fields for spending and income.
      - `comparison_until` string: Inclusive comparison range date (YYYY-MM-DD); supply all four date fields for spending and income.
  - ActionsDatasetQueryRequest
    - `dataset` 'actions', required: Which declared dataset to query. `candor data list` names them.
    - `filters` ActionsDatasetQueryFilters
      - `cursor` string: Omit for the first page. To continue, use the exact next_actions entry from the preceding response and preserve its filters; do not construct or edit the opaque cursor.
      - `limit` integer
      - `task_key` string

## Response `200`

Bounded dataset result envelope.

- ResponseEnvelope
  - `schema_version` string, required
  - `generated_at` string, date-time, required
  - `request_id` string, required
  - `status` 'success' | 'partial_success' | 'action_required' | 'error', required
  - `user_message` string: Optional concise user-safe message the calling agent may adapt.
  - `data_freshness` DataFreshness
    - `balances_last_synced_at` string
    - `coverage` 'complete' | 'partial' | 'stale' | 'unavailable', required
    - `holdings_last_synced_at` string
    - `transactions_last_synced_at` string
  - `metadata` object: Response-level protocol metadata such as package compatibility and workspace opening identity or timing. It is not financial workspace data and must not be treated as attention.
    - `view_url` string, uri: Authenticated dashboard destination related to this response. May open a section rather than reproduce the returned records or filters. Per-record view_url values identify exact supported record views. Use returned URLs instead of constructing paths.
  - `warnings` object[], required
  - `errors` AgentError[], required
    - `code` string, required
    - `expires_at` string
    - `idempotency_key` string: Stable key to reuse when retrying this identical logical operation.
    - `message` string, required
    - `recovery_url` string, uri
    - `required_capability` string
    - `retry_after_seconds` integer: Machine-actionable delay before retrying the identical logical operation.
    - `retryable` boolean, required
    - `suggested_command` string
  - `next_actions` AgentAction[], required
    - `intent` string, required
    - `command` string, required
    - `args` object, required
    - `shell` string, required
  - `action` WorkspaceAction
    - `id` string, required
    - `operation` string, required
    - `reason` string, required
    - `root_action_id` string, required
    - `parent_action_id` string
    - `task_key` string
    - `status` 'started' | 'succeeded' | 'refused' | 'failed', required
    - `created_at` string, date-time, required
    - `completed_at` string, date-time
  - `data` object, nullable, required: Operation-specific result data, or null when the request ends in an error.

## Other responses

- `default`: Structured Candor error envelope with machine-readable codes, recovery guidance, and retry timing when applicable.

---

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