# OData Query Parameters

Verso API supports OData query parameters for filtering, sorting, and paginating results on all GET endpoints. This guide covers the available query options with practical examples.

:::info[Route Pattern]
All examples use the **Partner route** pattern: `/partners/5/tenants/10/{resource}`. Replace with your actual partnerId and tenantId.
:::

## Query Parameters Overview

| Parameter | Description | Example |
|-----------|-------------|---------|
| `filter` | Filter results by conditions | `filter=status eq 'Active'` |
| `orderBy` | Sort results | `orderBy=created desc` |
| `select` | Choose specific fields | `select=id,name,email` |
| `top` | Limit number of results | `top=10` |
| `skip` | Skip first N results | `skip=20` |

## Filtering with filter

### Comparison Operators

| Operator | Description | Example |
|----------|-------------|---------|
| `eq` | Equal | `status eq 'Active'` |
| `ne` | Not equal | `status ne 'Inactive'` |
| `gt` | Greater than | `salary gt 50000` |
| `ge` | Greater than or equal | `age ge 18` |
| `lt` | Less than | `hours lt 40` |
| `le` | Less than or equal | `count le 100` |

### String Functions

| Function | Description | Example |
|----------|-------------|---------|
| `contains` | Contains substring | `contains(name, 'John')` |
| `startswith` | Starts with | `startswith(email, 'admin')` |
| `endswith` | Ends with | `endswith(email, '@company.com')` |

### Logical Operators

| Operator | Description | Example |
|----------|-------------|---------|
| `and` | Logical AND | `status eq 'Active' and age gt 18` |
| `or` | Logical OR | `role eq 'Admin' or role eq 'Manager'` |
| `not` | Logical NOT | `not contains(name, 'Test')` |

### Examples

```bash title="Filter Active Employees"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?filter=status eq 'Active'" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="Filter by Division"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?filter=divisions/any(d: d eq 'Sales')" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="Filter by Date Range"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/payruns/jobs?filter=periodStart ge 2025-01-01T00:00:00Z and periodStart lt 2025-02-01T00:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

:::tip
When using `filter` in URLs, remember to URL-encode special characters like spaces. Most HTTP clients handle this automatically.
:::

## Sorting with orderBy

Sort results by one or more fields in ascending (`asc`) or descending (`desc`) order.

### Single Field

```bash title="Sort by Name (Ascending)"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?orderBy=lastName asc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="Sort by Created Date (Descending)"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/users?orderBy=created desc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Multiple Fields

```bash title="Sort by Multiple Fields"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?orderBy=lastName asc, firstName asc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Field Selection with select

Return only specific fields to reduce response size.

```bash title="Select Specific Fields"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?select=id,identifier,firstName,lastName" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**
```json
[
  {
    "id": 1,
    "identifier": "emp001@company.com",
    "firstName": "Jean",
    "lastName": "Dupont"
  }
]
```

:::info
Using `select` can significantly improve performance by reducing payload size, especially for large datasets.
:::

## Pagination with top and skip

### Limit Results

```bash title="Get First 10 Results"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?top=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Pagination Pattern

```bash title="Page 1 (items 1-10)"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?top=10&skip=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="Page 2 (items 11-20)"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?top=10&skip=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="Page 3 (items 21-30)"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?top=10&skip=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Combined Queries

Combine multiple parameters for powerful queries:

```bash title="Complex Query"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/employees?filter=status eq 'Active'&orderBy=lastName asc&select=id,firstName,lastName&top=20&skip=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

This query:
1. Filters for active employees
2. Sorts by last name alphabetically
3. Returns only id, firstName, and lastName
4. Limits to 20 results
5. Starts from the first result

## Endpoint-Specific Examples

### Query Users

```bash title="Get Active Users"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/users?filter=status eq 'Active'&orderBy=lastName" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query Payrun Jobs

```bash title="Get Recent Completed Jobs"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/payruns/jobs?filter=jobStatus eq 'Draft'&orderBy=created desc&top=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

:::info[Job Status Values]
Payrun jobs can return to `Draft` after a successful asynchronous calculation. Require a non-null
`jobEnd` (or terminal `Forecast`/`Complete`) before reading results; `Draft` alone can still mean
queued or running. `Abort` and `Cancel` are failures.
:::

### Query Payroll Results

```bash title="Get Results for Specific Payrun"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/payrollresults?filter=payrunJobId eq 8" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query Payroll Result Sets (with Pagination)

For detailed wage type breakdowns, use `/payrollresults/sets`. The `payrunJobId` query parameter is **required** to scope results to a specific payrun job:

```bash title="Get Result Sets for a Payrun Job (recommended)"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/payrollresults/sets?payrunJobId=8" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="With Pagination"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/payrollresults/sets?payrunJobId=8&top=50&skip=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```bash title="Combine with Additional Filters"
curl -X GET "https://api.versohq.io/partners/5/tenants/10/payrollresults/sets?payrunJobId=8&filter=status eq 'Active'" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

:::info[Dedicated Query Parameters]
Some endpoints support **dedicated query parameters** as a shorthand for common filters. For example, `?payrunJobId=8` is equivalent to `?filter=payrunJobId eq 8`. When both are provided, they are combined with `and`.
:::

:::warning[Large Batches]
For payrun jobs with 100+ employees, always use pagination (`top` and `skip` parameters) to avoid timeouts. Recommended page size: 50 results.
:::

## Best Practices

1. **Always paginate large datasets** - Use `top` and `skip` for collections
2. **Select only needed fields** - Use `select` to reduce payload size
3. **Index-friendly filters** - Filter on indexed fields when possible
4. **Combine filters efficiently** - Use `and` to narrow results early

## Next Steps

- [Error Handling](/guides/error-handling) - Handle query errors
- [API Reference](/api) - Explore all endpoints
- [Quickstart](/quickstart) - Complete workflow example
