# Filter Object Definition V2

The Filter Object is the standard structure for refining data in Finout API V2. It is used in two contexts:

* [**Cost and Usage API V2**](https://docs.finout.io/api/finout-api/finout-api-v2/cost-and-usage-api-v2) — to scope query results to specific dimensions, providers, or tag values.
* **Virtual Tag rules for Virtual Tags API V2 (coming soon)** — to define the conditions that assign records to a specific tag value (e.g., "Team A" or "Project X"), with an optional default value for records that match no rule.

The same filter structure applies in both contexts.

***

### Filter structure

Filters support two levels of complexity.

#### Simple condition (no logical operator)

Use a direct condition object when you have a single filter requirement.

```json
{
  "filters": {
    "costCenter": "AWS",
    "key": "aws_account_name",
    "type": "tag",
    "displayName": "Account Name",
    "operator": "oneOf",
    "value": ["004a533177", "0371d7d3bf"]
  }
}
```

#### Complex conditions (nested logical operators)

Use `AND` and `OR` keys to group multiple conditions. You can nest them to any depth for complex logic.

```json
{
  "filters": {
    "AND": [
      {
        "costCenter": "AWS",
        "key": "region",
        "type": "billing_dimension",
        "displayName": "Regions",
        "operator": "oneOf",
        "value": ["us-east-1", "us-east-2", "eu-central-1"]
      },
      {
        "costCenter": "Global",
        "key": "cost_center_type",
        "type": "billing_dimension",
        "displayName": "Cost Center",
        "operator": "oneOf",
        "value": ["AWS"]
      }
    ]
  }
}
```

***

### Filter object fields

| Field         | Type   | Required    | Description                                                                                                                                                                                           | Example                                                                                  |
| ------------- | ------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `costCenter`  | string | Yes         | The cost center associated with the filter.                                                                                                                                                           | `"AWS"`, `"GCP"`, `"Kubernetes"`, `"Snowflake"`, `"Datadog"`, `"Azure"`, `"Custom Cost"` |
| `key`         | string | Yes         | The field identifier to filter on. Retrieve valid keys from [Query Language API V2](https://docs.finout.io/api/finout-api/finout-api-v2/query-language-api-v2) `/keys`.                               | `"deployment"`                                                                           |
| `type`        | string | Yes         | The key type. Use `virtual_tag` when filtering on Virtual Tags. Retrieve valid types from [Query Language API V2 `/keys`](https://docs.finout.io/api/finout-api/finout-api-v2/query-language-api-v2). | `"billing_dimension"`, `"virtual_tag"`                                                   |
| `operator`    | string | Yes         | The comparison operator to apply. See [Supported operators ](#supported-operators)below.                                                                                                              | `"oneOf"`                                                                                |
| `value`       | array  | Conditional | The values to match against. Not required for `exists` and `notExists` operators.                                                                                                                     | `["us-east-1", "us-east-2"]`                                                             |
| `displayName` | string | No          | The human-readable label for the field as shown in Finout. Optional and informational only.                                                                                                           | `"Account Name"`                                                                         |

***

### Supported operators

| Operator      | Requires `value` | Description                                                          |
| ------------- | ---------------- | -------------------------------------------------------------------- |
| `oneOf`       | Yes              | Matches if the field value equals any value in the array.            |
| `notOneOf`    | Yes              | Matches if the field value does not equal any value in the array.    |
| `is`          | Yes              | Matches if the field value is exactly equal to the specified value.  |
| `notIs`       | Yes              | Matches if the field value is not equal to the specified value.      |
| `contains`    | Yes              | Matches if the field value contains the specified substring.         |
| `notContains` | Yes              | Matches if the field value does not contain the specified substring. |
| `exists`      | No               | Matches if the field value exists (is not null or empty).            |
| `notExists`   | No               | Matches if the field value does not exist (is null or empty).        |

***

### Supported types

Retrieve the exact `type` values for your keys from the [Query Language API V2](https://docs.finout.io/api/finout-api/finout-api-v2/query-language-api-v2) `/keys` endpoint.

***

### Examples

#### Example 1 — Three-rule Virtual Tag configuration

This example shows a Virtual Tag with three rules. Records are evaluated against each rule in order. The first rule that matches determines the tag value assigned to the record. If no rule matches, the record receives the `defaultValue`.

```json
{
  "requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "accountId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "name": "Test",
  "rules": [
    {
      "to": "Finout",
      "filters": {
        "AND": [
          {
            "costCenter": "AWS",
            "key": "aws_account_name",
            "type": "billing_dimension",
            "displayName": "Account Name",
            "operator": "oneOf",
            "value": ["Finout"]
          },
          {
            "costCenter": "AWS",
            "key": "f_operation",
            "type": "billing_dimension",
            "displayName": "API Operation",
            "operator": "oneOf",
            "value": ["AAAA"]
          },
          {
            "costCenter": "Datadog",
            "key": "service",
            "type": "billing_dimension",
            "displayName": "Cost per Customer",
            "operator": "oneOf",
            "value": ["Abra"]
          }
        ]
      }
    },
    {
      "to": "Finout-Subaccount",
      "filters": {
        "costCenter": "AWS",
        "key": "aws_account_name",
        "type": "tag",
        "displayName": "Account Name",
        "operator": "oneOf",
        "value": ["Finout-Subaccount"]
      }
    },
    {
      "to": "AWS",
      "filters": {
        "costCenter": "Global",
        "key": "cost_center_type",
        "type": "billing_dimension",
        "displayName": "Cost Center",
        "operator": "oneOf",
        "value": ["AWS"]
      }
    }
  ],
  "category": "Project",
  "createdBy": "User",
  "updatedBy": "User",
  "createdAt": "Wed Mar 13 2024 15:40:46 GMT+0000 (Greenwich Mean Time)",
  "updatedAt": "Thu Mar 21 2024 10:49:17 GMT+0000 (Greenwich Mean Time)",
  "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "defaultValue": "Untagged"
}
```

**How this rule set works:**

The **first rule** assigns records to `"Finout"` when all three conditions match (AND logic):

* AWS `aws_account_name` billing dimension equals `Finout`
* AWS `f_operation` billing dimension equals `AAAA`
* Datadog `service` billing dimension equals `Abra`

The **second rule** assigns records to `"Finout-Subaccount"` when a single condition matches:

* AWS `aws_account_name` tag equals `Finout-Subaccount`

The **third rule** assigns records to `"AWS"` when a single condition matches:

* Global `cost_center_type` billing dimension equals `AWS`

Records that match none of the rules receive the default value `"Untagged"`.

***

#### Example 2 — Nested AND / OR logic

This example shows two rules using nested `AND` and `OR` operators. The first rule uses the logic: `(condition 1 OR condition 2) AND condition 3`.

```json
{
  "requestId": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "accountId": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "name": "exampleName",
  "rules": [
    {
      "to": "Tag1",
      "filters": {
        "AND": [
          {
            "OR": [
              {
                "costCenter": "Azure",
                "key": "accountownerid",
                "type": "tag",
                "displayName": "Account Owner Id",
                "operator": "oneOf",
                "value": ["ServiceA", "ServiceB", "ServiceC"]
              },
              {
                "costCenter": "Global",
                "key": "cost_center_type",
                "type": "billing_dimension",
                "displayName": "Cost Center",
                "operator": "oneOf",
                "value": ["AccountX", "AccountY"]
              }
            ]
          },
          {
            "costCenter": "GCP",
            "key": "department",
            "type": "tag",
            "displayName": "Service Name",
            "operator": "oneOf",
            "value": ["ServiceA", "ServiceB"]
          }
        ]
      }
    },
    {
      "to": "Tag2",
      "filters": {
        "costCenter": "AWS",
        "key": "s3_bucket",
        "type": "resource",
        "displayName": "Account Name",
        "operator": "oneOf",
        "value": ["AccountZ", "AccountW"]
      }
    }
  ],
  "createdBy": "CreatorName",
  "updatedBy": "UpdaterName",
  "createdAt": "Date and Time",
  "updatedAt": "Date and Time",
  "id": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "defaultValue": "DefaultTag"
}
```

**How this rule set works:**

The **first rule** assigns records to `"Tag1"` when the following combined condition matches:

* (Azure `accountownerid` tag is one of `ServiceA`, `ServiceB`, or `ServiceC` **OR** Global `cost_center_type` is one of `AccountX` or `AccountY`) **AND**
* GCP `department` tag is one of `ServiceA` or `ServiceB`

The **second rule** assigns records to `"Tag2"` when a single condition matches:

* AWS `s3_bucket` resource value is one of `AccountZ` or `AccountW`

Records that match neither rule receive the default value `"DefaultTag"`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.finout.io/api/finout-api/finout-api-v2/filter-object-definition-v2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
