> ## Documentation Index
> Fetch the complete documentation index at: https://docs.artu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Filtering

> Filter and query records with type-safe helpers

The SDK provides type-safe filter helpers for querying records.

## Basic Filtering

Pass filter objects to `list()` methods:

```typescript theme={null}
const { data } = await sdk.clients.list({
  filter: { type: "individual" },
});
```

Multiple filter properties are combined with AND logic:

```typescript theme={null}
const { data } = await sdk.clients.list({
  filter: {
    type: "individual",
  },
});
```

## Metadata filters

Use `metadataFilters` when you need exact key/value matches on `metadata`. Entries are AND-ed together.

```typescript theme={null}
const { data } = await sdk.transactions.list({
  filter: {
    metadataFilters: [
      { key: "source", value: "api" },
      { key: "region", value: "mx" },
    ],
  },
});
```

Supported on: clients, addresses, bank accounts, contact methods, documents, alerts, and transactions.

## Filter Helpers

Import helpers for building filters:

```typescript theme={null}
import {
  // String filters
  contains,
  startsWith,
  endsWith,
  equals,
  notEquals,
  // Array filters
  oneOf,
  notOneOf,
  // Date filters
  dateRange,
  after,
  before,
  onOrAfter,
  onOrBefore,
  // Number filters
  numberRange,
  greaterThan,
  lessThan,
  atLeast,
  atMost,
  // Boolean filters
  isTrue,
  isFalse,
  // Null filters
  isNull,
  isNotNull,
} from "@artu-ai/compliance-sdk";
```

## String Filters

### Contains

Match if field contains substring (case-insensitive):

```typescript theme={null}
await sdk.clients.list({
  filter: { name: contains("García") },
});
// Matches: "Juan García", "García López", "María García Hernández"
```

### Starts With

Match if field starts with prefix:

```typescript theme={null}
await sdk.clients.list({
  filter: { name: startsWith("Juan") },
});
// Matches: "Juan García", "Juan López", "Juana Martínez"
```

### Ends With

Match if field ends with suffix:

```typescript theme={null}
await sdk.clients.list({
  filter: { email: endsWith("@company.com") },
});
```

### Equals / Not Equals

Exact match or exclusion:

```typescript theme={null}
await sdk.clients.list({
  filter: { rfc: equals("XAXX010101000") },
});

await sdk.clients.list({
  filter: { status: notEquals("deleted") },
});
```

## Array Filters

### One Of

Match any of the values (OR):

```typescript theme={null}
await sdk.clients.list({
  filter: { type: oneOf("individual", "company") },
});
// Matches if type is "individual" OR "company"
```

### Not One Of

Exclude values:

```typescript theme={null}
await sdk.clients.list({
  filter: { status: notOneOf("deleted", "archived") },
});
// Matches if status is NOT "deleted" AND NOT "archived"
```

## Date Filters

### Date Range

Inclusive range:

```typescript theme={null}
await sdk.transactions.list({
  filter: {
    createdAt: dateRange(new Date("2024-01-01"), new Date("2024-12-31")),
  },
});
// Matches dates from Jan 1 to Dec 31, 2024 (inclusive)
```

### After / Before

Exclusive comparisons:

```typescript theme={null}
await sdk.transactions.list({
  filter: { createdAt: after(new Date("2024-01-01")) },
});
// Matches dates after Jan 1, 2024 (not including Jan 1)

await sdk.transactions.list({
  filter: { createdAt: before(new Date("2024-12-31")) },
});
// Matches dates before Dec 31, 2024 (not including Dec 31)
```

### On Or After / On Or Before

Inclusive comparisons:

```typescript theme={null}
await sdk.transactions.list({
  filter: { createdAt: onOrAfter(new Date("2024-01-01")) },
});
// Matches dates >= Jan 1, 2024

await sdk.transactions.list({
  filter: { createdAt: onOrBefore(new Date("2024-12-31")) },
});
// Matches dates <= Dec 31, 2024
```

## Number Filters

### Number Range

Inclusive range:

```typescript theme={null}
await sdk.transactions.list({
  filter: { amount: numberRange(1000, 10000) },
});
// Matches amounts from 1000 to 10000 (inclusive)
```

### Comparisons

```typescript theme={null}
// Greater than (exclusive)
await sdk.transactions.list({
  filter: { amount: greaterThan(1000) },
});
// Matches amounts > 1000

// Less than (exclusive)
await sdk.transactions.list({
  filter: { amount: lessThan(10000) },
});
// Matches amounts < 10000

// At least (inclusive)
await sdk.transactions.list({
  filter: { amount: atLeast(5000) },
});
// Matches amounts >= 5000

// At most (inclusive)
await sdk.transactions.list({
  filter: { amount: atMost(50000) },
});
// Matches amounts <= 50000
```

## Boolean Filters

```typescript theme={null}
await sdk.clients.list({
  filter: { isActive: isTrue() },
});

await sdk.clients.list({
  filter: { isDeleted: isFalse() },
});
```

## Null Filters

```typescript theme={null}
// Find records where field is null
await sdk.clients.list({
  filter: { deletedAt: isNull() },
});

// Find records where field is not null
await sdk.clients.list({
  filter: { rfc: isNotNull() },
});
```

## Combining Filters

Combine multiple filters (AND logic):

```typescript theme={null}
await sdk.clients.list({
  filter: {
    type: "individual",
    name: contains("García"),
    createdAt: after(new Date("2024-01-01")),
  },
});
```

## Filter with Pagination

```typescript theme={null}
const { data, pagination } = await sdk.clients.list({
  filter: {
    type: oneOf("individual", "company"),
    createdAt: dateRange(startDate, endDate),
  },
  limit: 50,
});

// Iterate with filter
for await (const client of sdk.clients.iterate({
  type: "individual",
})) {
  console.log(client.name);
}
```
