Query web analytics data from Flowsery Analytics — a privacy-first web analytics platform. Retrieve real-time visitors, time series, breakdowns (device, page...
---
name: flowsery
description: Query web analytics data from Flowsery Analytics — a privacy-first web analytics platform. Retrieve real-time visitors, time series, breakdowns (device, page, country, referrer, campaign, channel, exit link, and 24 dimensions total), visitor profiles with activity timelines, and track/manage custom goals and revenue attribution. Use when the user wants to check their website traffic, analyze visitor behavior, view revenue data, track conversions, or query any analytics metric from their Flowsery-tracked sites.
homepage: https://flowsery.com
metadata: { 'openclaw': { 'emoji': '📊', 'primaryEnv': 'FLOWSERY_API_KEY', 'requires': { 'env': ['FLOWSERY_API_KEY'] } } }
---
# Flowsery Analytics
Privacy-first web analytics. Query real-time visitors, breakdowns, time series, revenue, goals, and visitor profiles — all via one API.
## Setup
1. Sign up at https://flowsery.com/signup
2. Add your website and install the tracking snippet
3. Go to the workspace-level API Tokens page and create a workspace API token
4. Set the environment variable:
```bash
export FLOWSERY_API_KEY="flow_ws_your-token-here"
```
Base URL: `https://analytics.flowsery.com/analytics/api/v1`
Auth header: `Authorization: Bearer $FLOWSERY_API_KEY`
Workspace API tokens use the `flow_ws_` prefix. Use these for API, MCP, OpenClaw, and multi-website access. Website API keys use the `flow_` prefix and are scoped to a single website, mainly for server-side custom goal and payment ingestion. Treat both like passwords — never expose them in client-side code.
## Core Workflow
### 1. List accessible websites
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
https://analytics.flowsery.com/analytics/api/v1/websites
```
With a workspace token, choose the website and pass `websiteId=<id>` or `domain=<domain>` on subsequent API calls. With a website key, this returns only the scoped website.
### 2. Check website metadata
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/metadata?websiteId=WEBSITE_ID"
```
Returns `{ "status": "success", "data": [{ "domain", "timezone", "name", "logo", "kpiColorScheme", "kpi", "currency" }] }`. Use the `timezone` and `currency` values for subsequent queries.
### 3. Get site overview (aggregated metrics)
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/overview?websiteId=WEBSITE_ID&startAt=2026-01-01&endAt=2026-01-31&timezone=America/New_York"
```
Returns: `visitors`, `sessions`, `bounce_rate`, `avg_session_duration`, `revenue`, `revenue_per_visitor`, `conversion_rate`.
Omit date params for all-time data. Use `fields` param to select specific metrics: `?fields=visitors,revenue`.
### 4. Get time series data
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/timeseries?websiteId=WEBSITE_ID&interval=day&fields=visitors,sessions,revenue&startAt=2026-03-01&endAt=2026-03-31"
```
Intervals: `hour`, `day`, `week`, `month`. Returns timestamped data buckets with totals.
Response includes `data` array, `totals` object (with `visitors`, `sessions`, `revenue`, `revenueBreakdown`), and `pagination`.
### 5. Check real-time visitors
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/realtime?websiteId=WEBSITE_ID"
```
Returns `{ "data": [{ "visitors": 42 }] }` — active visitors in the last 5 minutes.
### 6. Get breakdown reports
Each returns top items for a dimension with visitor/session counts. All accept date range, pagination, and filter params.
```bash
# Top pages
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/pages?websiteId=WEBSITE_ID&startAt=2026-03-01&endAt=2026-03-31&limit=20"
# Top referrers
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/referrers?websiteId=WEBSITE_ID&startAt=2026-03-01&endAt=2026-03-31"
# Countries
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/countries?websiteId=WEBSITE_ID&startAt=2026-03-01&endAt=2026-03-31"
# Devices (desktop/mobile/tablet)
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/devices?websiteId=WEBSITE_ID&startAt=2026-03-01&endAt=2026-03-31"
# Marketing channels
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/channels?websiteId=WEBSITE_ID&startAt=2026-03-01&endAt=2026-03-31"
```
Available breakdown endpoints: `pages`, `referrers`, `countries`, `regions`, `cities`, `devices`, `browsers`, `operating-systems`, `campaigns`, `hostnames`, `channels`, `goals`.
For any dimension, use the generic breakdown:
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/breakdown?websiteId=WEBSITE_ID&dimension=utm_source&startAt=2026-03-01&endAt=2026-03-31"
```
See [references/breakdown-dimensions.md](references/breakdown-dimensions.md) for all 24 dimensions.
### 7. Get a visitor profile
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/visitors/VISITOR_ID_HERE?websiteId=WEBSITE_ID"
```
Returns comprehensive visitor data:
- **identity**: country, region, city, browser, OS, device type, viewport
- **source**: original traffic source with favicon URL
- **activity**: visit count, page views, first/last visit, visited pages, completed goals
- **revenue**: total revenue, customer flag, time to first conversion (seconds)
- **profile**: identified user data (userId, name, email) or null for anonymous visitors
- **activityTimeline**: merged chronological list of all pageviews, goals, and payments
The visitor ID comes from the `_fs_vid` browser cookie set by the Flowsery tracking script.
### 8. Track a custom goal
```bash
curl -X POST https://analytics.flowsery.com/analytics/api/v1/goals \
-H "Authorization: Bearer $FLOWSERY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"websiteId": "WEBSITE_ID",
"visitorUid": "VISITOR_UID_FROM_COOKIE",
"name": "newsletter_signup",
"metadata": { "plan": "pro", "source": "pricing_page" }
}'
```
- `name` (required): lowercase letters, numbers, underscores, hyphens; max 64 chars
- `visitorUid` (recommended): from the `_fs_vid` browser cookie
- `metadata` (optional): up to 10 key-value pairs (keys: lowercase, max 64 chars; values: max 255 chars)
The visitor must have at least one recorded pageview before a goal can be created.
### 9. Record a payment
> If you use Stripe, LemonSqueezy, or Polar, payments are tracked automatically when connected. Use this endpoint only for other providers.
```bash
curl -X POST https://analytics.flowsery.com/analytics/api/v1/payments \
-H "Authorization: Bearer $FLOWSERY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"websiteId": "WEBSITE_ID",
"amount": 29.99,
"currency": "USD",
"transactionId": "payment_456",
"visitorUid": "VISITOR_UID_FROM_COOKIE",
"email": "customer@example.com"
}'
```
Required: `amount`, `currency`, `transactionId`. Optional: `visitorUid`, `sessionUid`, `email`, `name`, `customerId`, `isRenewal` (boolean), `isRefund` (boolean).
### 10. Delete goal events
```bash
curl -X DELETE "https://analytics.flowsery.com/analytics/api/v1/goals?websiteId=WEBSITE_ID&name=signup&startAt=2026-01-01T00:00:00Z&endAt=2026-01-31T23:59:59Z" \
-H "Authorization: Bearer $FLOWSERY_API_KEY"
```
At least one filter required: `visitorId`, `name`, `startAt`, `endAt`.
**WARNING**: Without a date range, matching records are deleted across the entire history.
### 11. Delete payment records
```bash
curl -X DELETE "https://analytics.flowsery.com/analytics/api/v1/payments?websiteId=WEBSITE_ID&transactionId=payment_456" \
-H "Authorization: Bearer $FLOWSERY_API_KEY"
```
At least one filter required: `transactionId`, `visitorId`, `startAt`, `endAt`.
**WARNING**: Without a date range, matching records are deleted across the entire history.
## Query Parameters
### Date range & pagination (all GET endpoints)
| Param | Type | Description |
| ----------- | ------- | -------------------------------------------------------------------- |
| `startAt` | string | ISO 8601 start date (e.g. `2026-01-01`) |
| `endAt` | string | ISO 8601 end date (e.g. `2026-01-31`) |
| `timezone` | string | IANA timezone (e.g. `America/New_York`). Falls back to site default. |
| `limit` | integer | Max results, 1-1000 (default: 100) |
| `offset` | integer | Pagination offset (default: 0) |
| `websiteId` | string | Website to query when using a workspace token |
| `domain` | string | Website domain to query when using a workspace token |
### Filters (all GET endpoints)
All filters use the `filter_` prefix.
| Filter | Description |
| --------------------- | ---------------------------------------------- |
| `filter_country` | Country name or code |
| `filter_region` | Region or state |
| `filter_city` | City name |
| `filter_device` | Device type: `desktop`, `mobile`, `tablet` |
| `filter_browser` | Browser: `Chrome`, `Safari`, `Firefox`, `Edge` |
| `filter_os` | OS: `Mac OS`, `Windows`, `iOS`, `Android` |
| `filter_referrer` | Referrer domain |
| `filter_ref` | `ref` URL parameter value |
| `filter_source` | `source` URL parameter value |
| `filter_via` | `via` URL parameter value |
| `filter_utm_source` | UTM source |
| `filter_utm_medium` | UTM medium |
| `filter_utm_campaign` | UTM campaign |
| `filter_utm_term` | UTM term |
| `filter_utm_content` | UTM content |
| `filter_page` | Page path |
| `filter_hostname` | Hostname/domain |
| `filter_entry_page` | Landing page |
| `filter_channel` | Marketing channel |
| `filter_goal` | Goal name |
Combine multiple filters to drill down:
```bash
curl -s -H "Authorization: Bearer $FLOWSERY_API_KEY" \
"https://analytics.flowsery.com/analytics/api/v1/pages?websiteId=WEBSITE_ID&filter_country=United%20States&filter_device=mobile&startAt=2026-03-01&endAt=2026-03-31"
```
## Response Format
**Success (200 OK):**
```json
{
"status": "success",
"data": { ... }
}
```
**Error:**
```json
{
"status": "error",
"error": { "code": 401, "message": "A descriptive error message" }
}
```
Error codes: `400` (invalid input), `401` (bad API key), `404` (not found), `500` (server error).
## Marketing Channels
Flowsery auto-classifies traffic into GA4-aligned channels:
| Channel | How it's classified |
| -------------- | ------------------------------------------------------------------- |
| Organic Search | Google, Bing, DuckDuckGo, etc. |
| Paid Search | utm_medium: cpc, ppc, paid_search |
| Organic Social | Facebook, Twitter, LinkedIn, Reddit, etc. |
| Paid Social | utm_medium: paid_social, social_cpc |
| Email | utm_medium: email, newsletter; or source: mailchimp, sendgrid, etc. |
| Display | utm_medium: display, banner, cpm |
| Referral | Other websites |
| Direct | No referrer |
| Affiliate | utm_medium: affiliate, partner |
| Video | utm_medium: video, paid_video |
| SMS | utm_medium: sms |
| Audio | utm_medium: audio, podcast |
## Tips for the Agent
### Read-only by default
Most commands are safe GET queries. The only write operations are:
- `POST /goals` — track a goal event
- `POST /payments` — record a payment
- `DELETE /goals` — delete goal events (irreversible)
- `DELETE /payments` — delete payment records (irreversible)
**Always confirm with the user before running DELETE operations.**
### Date handling
- When the user says "this month", "last week", "yesterday" — calculate the actual ISO dates
- Default to the last 30 days when no date range is specified
- With a workspace token, call `/websites` first and choose a `websiteId` or `domain`
- Always use UTC or the site's timezone (from the metadata endpoint)
### Revenue data is sensitive
When displaying payment or revenue data, ask the user about the appropriate level of detail before dumping raw numbers.
### Polling
Do not poll the `realtime` endpoint more than once per 5 seconds.
### Common agent tasks
| User says | What to do |
| ---------------------------------- | ------------------------------------------------------------------------------------------- |
| "How's my traffic?" | Call `overview` with last 30 days |
| "What are my top pages?" | Call `pages` with date range |
| "Where is my traffic coming from?" | Call `referrers` or `channels` |
| "How many visitors right now?" | Call `realtime` |
| "Show me traffic trends" | Call `timeseries` with `interval=day` |
| "Who is this visitor?" | Call `visitors/{id}` |
| "Track a signup" | Call `POST /goals` with name and visitor UID |
| "How's my revenue?" | Call `overview` with `fields=revenue,conversion_rate` or `timeseries` with `fields=revenue` |
| "Break down traffic by country" | Call `countries` |
| "Show me mobile vs desktop" | Call `devices` |
| "What campaigns are working?" | Call `campaigns` or `breakdown?dimension=utm_source` |
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit intent statement, inputs section with env vars and prerequisites, decision point logic for missing data and errors, output contract with json format and error codes, outcome signals with common success patterns, and edge case handling for rate limits, auth expiry, empty result sets, and pagination.
Privacy-first web analytics. query real-time visitors, breakdowns, time series, revenue, goals, and visitor profiles via one API.
use this skill when the user wants to check website traffic, analyze visitor behavior, view revenue data, track conversions, or query any analytics metric from their Flowsery-tracked sites. flowsery serves privacy-first analytics without storing personally identifiable information by default. query real-time visitor counts, aggregated metrics (visitors, sessions, bounce rate, revenue), time series trends, dimension breakdowns (pages, referrers, countries, devices, browsers, campaigns, channels, and 24+ custom dimensions), individual visitor profiles with activity timelines, and custom goal/payment events.
environment variables:
FLOWSERY_API_KEY (required): Bearer token starting with flow_sk_live_ or flow_sk_test_. generate at https://flowsery.com dashboard, site settings, api tab. treat as a password; never expose client-side.external connections:
https://analytics.flowsery.com/analytics/api/v1Authorization: Bearer $FLOWSERY_API_KEY_fs_vid browser cookie containing the visitor ID.prerequisites:
common inputs for queries:
startAt: ISO 8601 date (e.g. 2026-03-01). omit for all-time data.endAt: ISO 8601 date (e.g. 2026-03-31). omit for all-time data.timezone: IANA timezone string (e.g. America/New_York). falls back to site default if omitted.limit: integer 1-1000 (default 100) for pagination.offset: integer (default 0) for pagination start position.fields: comma-separated metric names to return only specific columns (e.g. visitors,revenue).dimension: custom breakdown dimension (e.g. utm_source, utm_medium, page). see breakdown-dimensions reference.filter_*: filter prefix queries (e.g. filter_country=United%20States, filter_device=mobile, filter_utm_source=google).input: FLOWSERY_API_KEY environment variable
action: issue GET request to https://analytics.flowsery.com/analytics/api/v1/metadata with auth header.
output: JSON object containing array of sites with keys: domain, timezone, name, logo, kpiColorScheme, kpi, currency.
error handling: if 401 returned, API key is invalid or expired. if 404, no sites found on this account. if 500, flowsery API is down.
input: startAt, endAt (optional ISO dates), timezone (optional IANA string), fields (optional metric names)
action: issue GET request to https://analytics.flowsery.com/analytics/api/v1/overview?startAt=DATE&endAt=DATE&timezone=TZ.
output: JSON object with keys: visitors, sessions, bounce_rate, avg_session_duration, revenue, revenue_per_visitor, conversion_rate. use fields query param to restrict output columns (e.g. ?fields=visitors,revenue).
note: omit date params to retrieve all-time aggregates.
input: interval (hour, day, week, month), fields (metric names), startAt, endAt, timezone (all optional)
action: issue GET request to https://analytics.flowsery.com/analytics/api/v1/timeseries?interval=day&fields=visitors,sessions,revenue&startAt=DATE&endAt=DATE.
output: JSON object with keys: data (array of timestamped buckets with metrics), totals (object with aggregated sums and revenueBreakdown), pagination.
input: none
action: issue GET request to https://analytics.flowsery.com/analytics/api/v1/realtime.
output: JSON object with key data containing array with single object { "visitors": N } representing active visitors in last 5 minutes.
throttle: do not poll more than once per 5 seconds.
input: dimension (e.g. pages, referrers, countries, devices, browsers, campaigns, channels, goals, regions, cities, hostnames, operating-systems), startAt, endAt, timezone, limit, offset, filter_* (optional)
action: issue GET request to one of the following:
https://analytics.flowsery.com/analytics/api/v1/pages?startAt=DATE&endAt=DATE&limit=20https://analytics.flowsery.com/analytics/api/v1/referrers?startAt=DATE&endAt=DATEhttps://analytics.flowsery.com/analytics/api/v1/countries?startAt=DATE&endAt=DATEhttps://analytics.flowsery.com/analytics/api/v1/devices?startAt=DATE&endAt=DATEhttps://analytics.flowsery.com/analytics/api/v1/browsers?startAt=DATE&endAt=DATEhttps://analytics.flowsery.com/analytics/api/v1/channels?startAt=DATE&endAt=DATEhttps://analytics.flowsery.com/analytics/api/v1/campaigns?startAt=DATE&endAt=DATEhttps://analytics.flowsery.com/analytics/api/v1/breakdown?dimension=DIM&startAt=DATE&endAt=DATE for any custom dimension (24+ supported)output: JSON array of dimension items, each with visitor count, session count, and dimension value.
input: VISITOR_ID (from _fs_vid cookie or from breakdown/overview endpoints)
action: issue GET request to https://analytics.flowsery.com/analytics/api/v1/visitors/VISITOR_ID_HERE.
output: JSON object with keys:
identity: country, region, city, browser, os, device_type, viewportsource: original referrer, traffic source, favicon urlactivity: visit count, page view count, first visit timestamp, last visit timestamp, list of visited page paths, list of completed goalsrevenue: total revenue attributed, is_customer boolean, time_to_first_conversion (seconds or null)profile: identified user data (userId, name, email) or null for anonymousactivityTimeline: merged chronological array of pageviews, goal completions, and payments with timestampsinput: visitorUid (optional, from _fs_vid cookie), name (required, goal name), metadata (optional, up to 10 key-value pairs)
action: issue POST request to https://analytics.flowsery.com/analytics/api/v1/goals with JSON body:
{
"visitorUid": "VISITOR_UID_FROM_COOKIE",
"name": "newsletter_signup",
"metadata": { "plan": "pro", "source": "pricing_page" }
}
constraints:
name must be lowercase letters, numbers, underscores, hyphens, max 64 charsmetadata keys must be lowercase, max 64 chars; values max 255 charsoutput: JSON confirmation with goal event ID and timestamp.
input: amount (required, float), currency (required, e.g. USD), transactionId (required, unique string), visitorUid (optional), sessionUid (optional), email (optional), name (optional), customerId (optional), isRenewal (optional boolean), isRefund (optional boolean)
action: issue POST request to https://analytics.flowsery.com/analytics/api/v1/payments with JSON body:
{
"amount": 29.99,
"currency": "USD",
"transactionId": "payment_456",
"visitorUid": "VISITOR_UID_FROM_COOKIE",
"email": "customer@example.com"
}
note: stripe, lemonsqueezy, and polar integrations track payments automatically. use this endpoint only for other payment processors.
output: JSON confirmation with payment record ID.
input: at least one filter required: visitorId, name, startAt, endAt
action: issue DELETE request to https://analytics.flowsery.com/analytics/api/v1/goals?name=signup&startAt=2026-01-01T00:00:00Z&endAt=2026-01-31T23:59:59Z.
output: JSON confirmation of number of records deleted.
warning: without a date range, all matching goal events across entire history are deleted. this is irreversible.
input: at least one filter required: transactionId, visitorId, startAt, endAt
action: issue DELETE request to https://analytics.flowsery.com/analytics/api/v1/payments?transactionId=payment_456.
output: JSON confirmation of number of records deleted.
warning: without a date range, all matching payment records across entire history are deleted. this is irreversible.
if API key is invalid or missing: return 401 error. stop execution. instruct user to generate a new API key or set FLOWSERY_API_KEY environment variable.
if no date range specified and user asks for trends: default to last 30 days. calculate startAt and endAt as ISO 8601 dates in UTC or site timezone.
if user asks "how's my traffic" with no context: call overview endpoint with last 30 days. if user specifies a period (this month, last quarter, etc), calculate actual ISO dates.
if user wants to track a goal but hasn't provided visitorUid: ask user for visitor ID or page context. if unavailable, note that goal may be anonymous and cannot be attributed to specific visitor.
if user wants to delete goal or payment records: always confirm intent first. do not execute DELETE without explicit user approval.
if query returns empty data array: return human-readable message (e.g. "no page data for this period") instead of raw empty JSON.
if API returns 400 (invalid input): validate all filter names, dimension names, and date formats against documented allowed values. suggest corrections.
if API returns 500 or timeout: retry up to 2 times with exponential backoff (1s, 2s). if still failing, report service is unavailable.
if pagination needed (result set > limit): use offset param to fetch next batch. continue until data array is empty or result count is less than limit.
if user asks about revenue but has not connected a payment provider: note that revenue data is only populated if user has connected stripe, lemonsqueezy, polar, or manually recorded payments via POST /payments.
all GET responses follow format:
{
"status": "success",
"data": { ... } or [ ... ]
}
all POST/DELETE responses include:
{
"status": "success",
"data": {
"id": "event_or_record_id",
"timestamp": "ISO 8601 timestamp",
"message": "descriptive text"
}
}
all error responses follow format:
{
"status": "error",
"error": {
"code": 400 | 401 | 404 | 500,
"message": "descriptive error text"
}
}
error codes:
date handling: all input dates must be ISO 8601 format (YYYY-MM-DD). response timestamps are ISO 8601 with milliseconds. all times respect the timezone param or site default.
pagination: all GET endpoints support limit and offset. set limit to 1-1000 (default 100). if result count equals limit, assume more records exist and use offset to fetch next batch.
metric availability: revenue, revenue_per_visitor, conversion_rate fields only populated if user has connected a payment provider or recorded payments via API. missing keys should not be assumed to be zero.
user knows the skill worked when:
common success patterns: