Source: https://datafa.st/docs/api/website/breakdowns/operating-systems
Markdown source: https://datafa.st/docs/api/website/breakdowns/operating-systems.md
Description: Return analytics broken down by operating system — visitors, attributed revenue, and payment count per row. Combine with `filter_*` parameters and date ranges to compare segments, just like dashboard breakdown tabs.

# Get operating system analytics

`GET https://datafa.st/api/v1/analytics/operating-systems`

Return analytics broken down by operating system — visitors, attributed revenue, and payment count per row. Combine with `filter_*` parameters and date ranges to compare segments, just like dashboard breakdown tabs.

Results are sorted by visitors descending. Omit `startAt` and `endAt` for all-time data.

> **Related:** [Filter your data](/docs/datafast-filters)

## Request

#### Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `fields` | string | No | Comma-separated response columns. Omit to return all valid fields for this endpoint. Valid values: `operating_system`, `visitors`, `revenue`, `payments`. Example: `fields=visitors,revenue,payments`. |
| `websiteId` | string | Required with dft_ | Required with a `dft_` account token on Website API routes. Omit with a `df_` website key. Example: `?websiteId=665f0b3c4d2e1a0012345678`. |
| `startAt` | string | No* | Start of the reporting window. Use `YYYY-MM-DD` for calendar days or an ISO timestamp. Must be provided together with `endAt`. Example: `startAt=2026-05-01`. |
| `endAt` | string | No* | End of the reporting window. Must be provided together with `startAt`. Example: `endAt=2026-05-21`. |
| `timezone` | string | No | Timezone used to interpret dates and group analytics buckets. Defaults to the website timezone. IANA timezone for dashboard periods and API date grouping. Examples: `"America/New_York"`, `"Europe/Paris"`, `"UTC"`. Defaults to the website timezone when omitted. |
| `limit` | number | No | Maximum rows to return. Default `100`, maximum `1000` on analytics endpoints and `250` on list visitors. Example: `limit=50`. |
| `offset` | number | No | Rows to skip before returning results. Use with `limit` for pagination. Default `0`. Example: `offset=50`. |
| `filter_country` | string | No | Limit results to one or more countries. Prefix with an operator: `is`, `is_not`. Accepts country names or codes. Example: `filter_country=US,Canada` or `filter_country=is_not:France`. |
| `filter_region` | string | No | Limit results by region or state. Example: `filter_region=California`. |
| `filter_city` | string | No | Limit results by city. Example: `filter_city=San Francisco`. |
| `filter_device` | string | No | Limit results by device type: `desktop`, `mobile`, or `tablet`. Example: `filter_device=mobile`. |
| `filter_browser` | string | No | Limit results by browser. Filtering `Safari` also includes Mobile Safari. Example: `filter_browser=Chrome,Safari`. |
| `filter_os` | string | No | Limit results by operating system. Example: `filter_os=iOS,Android`. |
| `filter_referrer` | string | No | Limit results by referrer domain or normalized source such as `Google` or `Direct/None`. Example: `filter_referrer=Google`. |
| `filter_page` | string | No | Limit results to visitors who viewed a page. Operators: `is`, `is_not`, `contains`, `does_not_contain`. Example: `filter_page=contains:/docs`. |
| `filter_entry_page` | string | No | Limit results by first page in the session. Same operators as `filter_page`. Example: `filter_entry_page=/pricing`. |
| `filter_hostname` | string | No | Limit results by tracked hostname. Example: `filter_hostname=app.example.com`. |
| `filter_goal` | string | No | Limit results to visitors who completed a goal. Example: `filter_goal=signup`. |
| `filter_utm_source` | string | No | Limit results by UTM source. Example: `filter_utm_source=google`. |
| `filter_utm_medium` | string | No | Limit results by UTM medium. Example: `filter_utm_medium=cpc`. |
| `filter_utm_campaign` | string | No | Limit results by UTM campaign. Example: `filter_utm_campaign=launch`. |
| `filter_utm_term` | string | No | Limit results by UTM term. Example: `filter_utm_term=brand-keyword`. |
| `filter_utm_content` | string | No | Limit results by UTM content. Example: `filter_utm_content=hero-cta`. |
| `filter_ref` | string | No | Limit results by the `ref` URL parameter. Example: `filter_ref=twitter`. |
| `filter_source` | string | No | Limit results by the `source` URL parameter. Example: `filter_source=newsletter`. |
| `filter_via` | string | No | Limit results by the `via` URL parameter. Example: `filter_via=partner`. |

#### Example filters

Combine `filter_*` query params with date ranges:

```http
GET /api/v1/analytics/timeseries?fields=visitors,revenue&interval=day&startAt=2026-05-01&endAt=2026-05-21&filter_device=mobile&filter_country=US
```

Operators: `is`, `is_not`, and `contains` (pages only). Full reference: [filter your data](/docs/datafast-filters).

## Response

Returns a JSON object with `status: "success"` and endpoint-specific fields in `data` (and `pagination` when the endpoint is paginated).

#### Response fields

| Field | Type | Description |
| --- | --- | --- |
| `data[].operating_system` | string | Operating system name. |
| `data[].visitors` | number | Number of unique visitors represented by this row or time bucket. Use it to compare traffic volume across dates, pages, sources, countries, devices, or campaigns. |
| `data[].revenue` | number | Revenue attributed to this row or time bucket, in the website currency. Use it to see which time periods or dimensions influenced paid conversions. |
| `data[].payments` | number | Number of payment events attributed to this row or time bucket. Use it when you need transaction count instead of revenue amount. |
| `pagination.limit` | number | Maximum number of rows returned in one response. Use with `offset` to paginate through long result sets. |
| `pagination.offset` | number | Number of rows to skip before returning results. Use it with `limit` for pagination. |
| `pagination.total` | number | Total rows. |

## Authentication

- **`df_` website API key:** The website is inferred from the key. You do not need a `websiteId` query parameter.
- **`dft_` account token:** Requires `analytics:read` permission and `?websiteId=` on every request. The token must be allowed to access that website.

Read [authentication and scopes](/docs/api/authentication) for token creation, permission lists, and scoped tokens.

### Errors

**400** — Invalid `fields` value, partial date range, or invalid filter.

**404** — Website not found.

See [API errors](/docs/api#errors) for the standard error envelope, auth failures, validation errors, permission errors, and rate limits.

## Code examples

### Example request

```bash
curl -X GET "https://datafa.st/api/v1/analytics/operating-systems?limit=20&startAt=2026-05-01&endAt=2026-05-19" \
  -H "Authorization: Bearer df_xxx"
```

### Success response

```json
{
  "status": "success",
  "data": [
    {
      "operating_system": "Mac OS",
      "visitors": 640,
      "revenue": 2200,
      "payments": 27
    }
  ],
  "pagination": {
    "limit": 20,
    "offset": 0,
    "total": 1
  }
}
```
