> For the complete documentation index, see [llms.txt](https://docs.goodfit.io/goodfit-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.goodfit.io/goodfit-docs/apis/dataset-api/filters.md).

# Filters

Filter companies by the data points in your Goodfit dataset.

Filters are accepted by:

* `POST /dataset/companies/search`, as `filters`
* `POST /dataset/exports`, as `exportConfig.filters`

### Available data points

Filters can reference data points that exist in your Goodfit dataset and are exposed through the API.

Call `GET /dataset/companies/fields` to see which data points you can filter on and which operators each accepts:

{% code overflow="wrap" %}

```
{
  "fields": [
    {
      "fieldName": "__match_sourcing_criteria",
      "fieldType": "Boolean",
      "operators": [
        "exists",
        "notExists",
        "booleanFalse",
        "booleanTrue",
        "booleanFalseOrNull"
      ],
      "description": "Does this company currently match sourcing criteria?"
    }
  ]
}
```

{% endcode %}

Exports also accept `__added_at` and `__updated_at`. See Incremental exports.

### Filter structure

A filter is a group containing one or more rules.

#### Group

| Field        | Type   | Description                                  |
| ------------ | ------ | -------------------------------------------- |
| `id`         | string | Identifier for the group, returned in errors |
| `combinator` | string | `and` or `or`                                |
| `rules`      | array  | Rules, or nested groups                      |

#### Rule

| Field      | Type   | Description                                                                          |
| ---------- | ------ | ------------------------------------------------------------------------------------ |
| `id`       | string | Identifier for the rule, returned in errors                                          |
| `field`    | string | The `fieldName` of the data point                                                    |
| `operator` | string | See Operators                                                                        |
| `value`    | varies | Depends on the operator. Omitted for `exists`, `notExists` and the boolean operators |

#### Example request

{% code overflow="wrap" %}

```
{
  "filters": {
    "id": "root",
    "combinator": "and",
    "rules": [
      {
        "id": "r1",
        "field": "data_point_a",
        "operator": "stringEqualOneOf",
        "value": [
          "x",
          "y"
        ]
      }
    ]
  },
  "limit": 100
}
```

{% endcode %}

#### Nested groups

Groups can be nested to combine `and` and `or` conditions:

{% code overflow="wrap" %}

```
{
  "id": "root",
  "combinator": "and",
  "rules": [
    {
      "id": "r1",
      "field": "data_point_a",
      "operator": "stringEqualOneOf",
      "value": [
        "x",
        "y"
      ]
    },
    {
      "id": "g1",
      "combinator": "or",
      "rules": [
        {
          "id": "r2",
          "field": "data_point_b",
          "operator": "gte",
          "value": 100
        },
        {
          "id": "r3",
          "field": "data_point_c",
          "operator": "booleanTrue"
        }
      ]
    }
  ]
}
```

{% endcode %}

Replace `data_point_a`, `data_point_b` and `data_point_c` with names returned by `GET /dataset/companies/fields`.

### Operators

The operators available depend on the data point's type.

#### All types

| Operator    | Value | Description                                                   |
| ----------- | ----- | ------------------------------------------------------------- |
| `exists`    | none  | Has a value                                                   |
| `notExists` | none  | Has no value. Empty strings and empty lists count as no value |

#### String and Picklist

| Operator                 | Value        | Description                                           |
| ------------------------ | ------------ | ----------------------------------------------------- |
| `stringEqualOneOf`       | `["x", "y"]` | Equals one of the values. Case-insensitive            |
| `stringNotEqualOneOf`    | `["x", "y"]` | Equals none of the values. Case-insensitive           |
| `stringContainsOneOf`    | `["x", "y"]` | Contains one of the values. Case-insensitive          |
| `stringNotContainsOneOf` | `["x", "y"]` | Contains none of the values. Case-insensitive         |
| `equalTo`                | `"x"`        | Equals the value. Case-sensitive for Picklist         |
| `notEqualTo`             | `"x"`        | Does not equal the value. Case-sensitive for Picklist |

#### Multipicklist and Array

| Operator                       | Value        | Description                                                        |
| ------------------------------ | ------------ | ------------------------------------------------------------------ |
| `arrayContainsAnyOf`           | `["x", "y"]` | Contains an item equal to one of the values. Case-sensitive        |
| `arrayNotContainsAnyOf`        | `["x", "y"]` | Contains no item equal to any of the values. Case-sensitive        |
| `arrayContainsAnySubstring`    | `["x", "y"]` | Contains an item that includes one of the values. Case-insensitive |
| `arrayNotContainsAnySubstring` | `["x", "y"]` | Contains no item that includes any of the values. Case-insensitive |
| `arrayLengthGt`                | `3`          | Has more than 3 items                                              |
| `arrayLengthGte`               | `3`          | Has 3 or more items                                                |
| `arrayLengthLt`                | `3`          | Has fewer than 3 items                                             |
| `arrayLengthLte`               | `3`          | Has 3 or fewer items                                               |

A list with no value counts as 0 items.

#### Number, Integer, Percentage and Currency

| Operator     | Value      | Description                        |
| ------------ | ---------- | ---------------------------------- |
| `equalTo`    | `10`       | Equals the value                   |
| `notEqualTo` | `10`       | Does not equal the value           |
| `gt`         | `10`       | Greater than the value             |
| `gte`        | `10`       | Greater than or equal to the value |
| `lt`         | `10`       | Less than the value                |
| `lte`        | `10`       | Less than or equal to the value    |
| `between`    | `[10, 50]` | Between the two values, inclusive  |

#### Boolean

| Operator             | Value | Description              |
| -------------------- | ----- | ------------------------ |
| `booleanTrue`        | none  | Is true                  |
| `booleanFalse`       | none  | Is false                 |
| `booleanFalseOrNull` | none  | Is false or has no value |

#### Date

| Operator             | Value                             | Description                      |
| -------------------- | --------------------------------- | -------------------------------- |
| `dateEqual`          | `"2026-01-31"`                    | On the date                      |
| `dateNotEqual`       | `"2026-01-31"`                    | Not on the date                  |
| `dateSince`          | `"2026-01-31"`                    | On or after the date             |
| `dateBefore`         | `"2026-01-31"`                    | Before the date                  |
| `dateBetween`        | `["2026-01-01", "2026-03-31"]`    | Between the two dates, inclusive |
| `dateSinceRelative`  | `{ "unit": "DAY", "amount": 30 }` | On or after 30 days ago          |
| `dateBeforeRelative` | `{ "unit": "DAY", "amount": 30 }` | Before 30 days ago               |

Dates are compared by day. Use the `YYYY-MM-DD` format.

For relative dates, `unit` is one of `DAY`, `WEEK`, `MONTH` or `YEAR`, and `amount` is a positive integer.

### Matching behaviour

* Negative operators, such as `stringNotEqualOneOf`, `notEqualTo` and `dateNotEqual`, also match companies where the data point has no value. Add an `exists` rule to exclude them.
* Rules with an empty value, such as `[]` or `""`, are ignored.
* A group with no rules matches all companies.
* `combinator` is case-insensitive.

### Errors

Invalid filters on a search return `400 Bad Request`, with the ID of each rule that failed validation:

{% code overflow="wrap" %}

```
{
  "error": "Bad request: Invalid filters: {\"r2\":\"INCORRECT_OPERATOR\"}",
  "code": "INVALID_REQUEST"
}
```

{% endcode %}

| Error                  | Meaning                                                                    |
| ---------------------- | -------------------------------------------------------------------------- |
| `UNKNOWN_FIELD`        | The data point does not exist in your dataset, or cannot be filtered on    |
| `INCORRECT_OPERATOR`   | The operator is not available for the data point's type                    |
| `INCORRECT_VALUES`     | The value is missing, a range is not a pair, or a relative date is invalid |
| `INCORRECT_COMBINATOR` | The `combinator` is not `and` or `or`                                      |

Filters on exports are not validated when the export is requested. An export with invalid filters ends with status `FAILED`.
