Wispr AI Team Insights API
The Team Insights API from Wispr AI — 7 operation(s) for team insights.
The Team Insights API from Wispr AI — 7 operation(s) for team insights.
openapi: 3.0.3
info:
title: Wispr Backend Analytics Team Insights API
description: Wispr Backend API
version: 0.5.2
tags:
- name: Team Insights
paths:
/api/v1/enterprise/insights/words-dictated:
get:
tags:
- Team Insights
summary: Get Words Dictated
description: Words Dictated headline + delta + timeseries. ``app_keys``/``app_categories`` use OR-semantics.
operationId: get_words_dictated
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
- name: start_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: Start Date
- name: end_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: End Date
- name: team_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
title: Team Id
- name: user_ids
in: query
required: false
schema:
type: array
items:
type: string
maxItems: 100
title: User Ids
- name: app_keys
in: query
required: false
schema:
type: array
items:
type: string
title: App Keys
- name: app_categories
in: query
required: false
schema:
type: array
items:
type: string
title: App Categories
- name: comparison_mode
in: query
required: false
schema:
anyOf:
- enum:
- rolling
- calendar
type: string
- type: 'null'
description: How pct_change picks the prior window. ``rolling`` = trailing N days vs prior N days (for Last 7/30 days). ``calendar`` = MoM/YoY shift (for This month, Last month, This year). Omit to use shape detection.
title: Comparison Mode
description: How pct_change picks the prior window. ``rolling`` = trailing N days vs prior N days (for Last 7/30 days). ``calendar`` = MoM/YoY shift (for This month, Last month, This year). Omit to use shape detection.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/WordsDictatedResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/enterprise/insights/words-dictated/export:
get:
tags:
- Team Insights
summary: Export Words Dictated
description: Dimensional CSV of words/dictations for the Usage page export popover.
operationId: export_words_dictated
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
- name: start_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: Start Date
- name: end_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: End Date
- name: team_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
title: Team Id
- name: user_ids
in: query
required: false
schema:
type: array
items:
type: string
maxItems: 100
title: User Ids
- name: app_keys
in: query
required: false
schema:
type: array
items:
type: string
title: App Keys
- name: app_categories
in: query
required: false
schema:
type: array
items:
type: string
title: App Categories
- name: columns
in: query
required: false
schema:
type: array
items:
enum:
- user
- email
- team
- app_type
- app
type: string
description: Dimensions to include as CSV columns. Order is fixed by the design; duplicates are deduped server-side.
title: Columns
description: Dimensions to include as CSV columns. Order is fixed by the design; duplicates are deduped server-side.
- name: comparison_mode
in: query
required: false
schema:
anyOf:
- enum:
- rolling
- calendar
type: string
- type: 'null'
description: Accepted for shape parity with ``/words-dictated`` — CSV export has no pct_change column so this is unused.
title: Comparison Mode
description: Accepted for shape parity with ``/words-dictated`` — CSV export has no pct_change column so this is unused.
responses:
'200':
description: CSV export
content:
text/csv:
schema:
type: string
format: binary
'413':
description: Export row cap exceeded — narrow filters and retry.
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/enterprise/insights/team-members:
get:
tags:
- Team Insights
summary: Get Team Members
description: Total members + active-user timeseries. ``mode`` controls per-day aggregation granularity.
operationId: get_team_members
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
- name: mode
in: query
required: false
schema:
enum:
- daily
- weekly
- monthly
- inactive
type: string
default: weekly
title: Mode
- name: start_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: Start Date
- name: end_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: End Date
- name: team_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
title: Team Id
- name: user_ids
in: query
required: false
schema:
type: array
items:
type: string
maxItems: 100
title: User Ids
- name: app_keys
in: query
required: false
schema:
type: array
items:
type: string
title: App Keys
- name: app_categories
in: query
required: false
schema:
type: array
items:
type: string
title: App Categories
- name: comparison_mode
in: query
required: false
schema:
anyOf:
- enum:
- rolling
- calendar
type: string
- type: 'null'
description: How pct_change picks the prior window. ``rolling`` = trailing N days vs prior N days. ``calendar`` = MoM/YoY shift. Omit to use shape detection.
title: Comparison Mode
description: How pct_change picks the prior window. ``rolling`` = trailing N days vs prior N days. ``calendar`` = MoM/YoY shift. Omit to use shape detection.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/TeamMembersResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/enterprise/insights/desktop-apps:
get:
tags:
- Team Insights
summary: Get Desktop Apps
description: Distinct app count + app list (top-2000 from CH, capped). ``app_keys``/``app_categories`` OR-semantics.
operationId: get_desktop_apps
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
- name: start_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: Start Date
- name: end_date
in: query
required: false
schema:
anyOf:
- type: string
format: date
- type: 'null'
title: End Date
- name: team_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
title: Team Id
- name: user_ids
in: query
required: false
schema:
type: array
items:
type: string
maxItems: 100
title: User Ids
- name: app_keys
in: query
required: false
schema:
type: array
items:
type: string
title: App Keys
- name: app_categories
in: query
required: false
schema:
type: array
items:
type: string
title: App Categories
- name: comparison_mode
in: query
required: false
schema:
anyOf:
- enum:
- rolling
- calendar
type: string
- type: 'null'
description: How pct_change picks the prior window. ``rolling`` = trailing N days vs prior N days. ``calendar`` = MoM/YoY shift. Omit to use shape detection.
title: Comparison Mode
description: How pct_change picks the prior window. ``rolling`` = trailing N days vs prior N days. ``calendar`` = MoM/YoY shift. Omit to use shape detection.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/DesktopAppsResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/enterprise/insights/impact:
get:
tags:
- Team Insights
summary: Get Impact
description: All Impact cards in one round trip. ``team_id`` is the only filter.
operationId: get_impact
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
- name: team_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
title: Team Id
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ImpactResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/enterprise/insights/filter-options:
get:
tags:
- Team Insights
summary: List Filter Options
description: 'Page-load dropdowns: teams + apps + categories.'
operationId: list_filter_options
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/FilterOptionsResponse'
'429':
description: Too Many Requests
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/enterprise/insights/filter-options/users:
get:
tags:
- Team Insights
summary: List User Filter Options
description: Typeahead user search over the requested enterprise.
operationId: list_user_filter_options
security:
- ApiKeyHeaderPatched: []
parameters:
- name: enterprise_id
in: query
required: true
schema:
type: string
format: uuid
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
title: Enterprise Id
description: Enterprise to query. Wispr admins may pass any; enterprise admins must pass their own.
- name: q
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Prefix on first/last/email
title: Q
description: Prefix on first/last/email
- name: limit
in: query
required: false
schema:
type: integer
maximum: 200
minimum: 1
default: 50
title: Limit
- name: offset
in: query
required: false
schema:
type: integer
maximum: 10000
minimum: 0
default: 0
title: Offset
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/UserFilterOptionsResponse'
'429':
description: Too Many Requests
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
UserFilterOptionsResponse:
properties:
users:
items:
$ref: '#/components/schemas/UserFilterOption'
type: array
title: Users
has_more:
type: boolean
title: Has More
default: false
type: object
required:
- users
title: UserFilterOptionsResponse
description: Per-keystroke typeahead — separate from FilterOptionsResponse due to different caching and rate-limit profile.
TeamMembersDailyPoint:
properties:
period:
type: string
format: date
title: Period
count:
type: integer
minimum: 0.0
title: Count
type: object
required:
- period
- count
title: TeamMembersDailyPoint
description: '``count`` is WAU(D) or MAU(D) for rolling-window modes.'
WordsDictatedWeeklyPoint:
properties:
period:
type: string
title: Period
desktop:
type: integer
minimum: 0.0
title: Desktop
mobile:
type: integer
minimum: 0.0
title: Mobile
type: object
required:
- period
- desktop
- mobile
title: WordsDictatedWeeklyPoint
description: '``period`` is the ISO date of the week''s Sunday (e.g. ``2026-04-12``).'
WordsDictatedResponse:
properties:
filters_applied:
$ref: '#/components/schemas/TeamInsightsFilters'
data_quality_flags:
items:
type: string
type: array
title: Data Quality Flags
total:
type: integer
minimum: 0.0
title: Total
pct_change_vs_prev_period:
anyOf:
- type: number
- type: 'null'
title: Pct Change Vs Prev Period
timeseries:
$ref: '#/components/schemas/WordsDictatedTimeseries'
type: object
required:
- filters_applied
- total
- timeseries
title: WordsDictatedResponse
description: 'Headline + delta + daily/weekly timeseries.
``pct_change_vs_prev_period`` is percent-scale (``12.34`` = 12.34%). The
prior period is picked by ``filters.comparison_mode`` when set, otherwise by
shape detection (calendar-aligned for YTD/MTD shapes, rolling otherwise).
Lifetime (no ``start_date``) falls back to L7 vs L7-L14. ``null`` when
prior=0 with non-zero current (undefined), or no comparable prior period
exists.'
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
AppFilterOption:
properties:
app_key:
type: string
title: App Key
display_name:
type: string
title: Display Name
category:
type: string
title: Category
type: object
required:
- app_key
- display_name
- category
title: AppFilterOption
description: A selectable app in the insights filter dropdown, with its display name and category.
TeamFilterOption:
properties:
id:
type: string
format: uuid
title: Id
name:
type: string
title: Name
type: object
required:
- id
- name
title: TeamFilterOption
description: A selectable team in the insights filter dropdown.
FeatureUtilization:
properties:
feature:
type: string
title: Feature
user_count:
type: integer
minimum: 0.0
title: User Count
feature_usage_count:
type: integer
minimum: 0.0
title: Feature Usage Count
type: object
required:
- feature
- user_count
- feature_usage_count
title: FeatureUtilization
description: Lifetime counts per feature (``dictionary`` / ``snippets`` / ``styles`` / ``transforms``).
ValueCalculator:
properties:
team_member_count:
type: integer
minimum: 0.0
title: Team Member Count
monthly_minutes_saved:
type: number
minimum: 0.0
title: Monthly Minutes Saved
monthly_cost_minor_units:
anyOf:
- type: integer
minimum: 0.0
- type: 'null'
title: Monthly Cost Minor Units
currency:
anyOf:
- type: string
- type: 'null'
title: Currency
type: object
required:
- team_member_count
- monthly_minutes_saved
- monthly_cost_minor_units
- currency
title: ValueCalculator
description: 'Inputs for the Impact tab ROI widget.
``monthly_minutes_saved`` is the team total over a trailing 30d window.
Frontend derives per-user as ``monthly_minutes_saved / team_member_count`` and
team value as ``(monthly_minutes_saved / 60) * salary_rate`` — shipping the
total (not pre-divided) keeps per-user rounding from amplifying by team size.
``monthly_cost_minor_units`` is the enterprise''s normalized post-discount
monthly recurring spend, in Stripe minor units (cents for USD, yen for JPY —
divide by ``10 ** Intl.NumberFormat(...).resolvedOptions().maximumFractionDigits``).
``currency`` is the Stripe-lowercase ISO 4217 code. ``monthly_cost_minor_units``
is null when we can''t compute the cost (no live sub, Stripe error). ``currency``
falls back to the DB-cached billing currency on Stripe errors so the FE stays
currency-locked across transient blips.'
WordsDictatedDailyPoint:
properties:
period:
type: string
format: date
title: Period
desktop:
type: integer
minimum: 0.0
title: Desktop
mobile:
type: integer
minimum: 0.0
title: Mobile
type: object
required:
- period
- desktop
- mobile
title: WordsDictatedDailyPoint
description: Words dictated on a single calendar day, split by desktop vs mobile.
UserFilterOption:
properties:
user_id:
type: string
title: User Id
name:
anyOf:
- type: string
- type: 'null'
title: Name
email:
anyOf:
- type: string
- type: 'null'
title: Email
type: object
required:
- user_id
title: UserFilterOption
description: A selectable user in the insights typeahead filter.
TeamInsightsFilters:
properties:
start_date:
anyOf:
- type: string
format: date
- type: 'null'
title: Start Date
end_date:
anyOf:
- type: string
format: date
- type: 'null'
title: End Date
team_id:
anyOf:
- type: string
format: uuid
- type: 'null'
title: Team Id
user_ids:
items:
type: string
type: array
maxItems: 100
title: User Ids
app_keys:
items:
type: string
type: array
title: App Keys
app_categories:
items:
type: string
type: array
title: App Categories
comparison_mode:
anyOf:
- type: string
enum:
- rolling
- calendar
- type: 'null'
title: Comparison Mode
type: object
title: TeamInsightsFilters
description: Filters echoed back on every response. Null date fields = all-time.
DesktopAppsResponse:
properties:
filters_applied:
$ref: '#/components/schemas/TeamInsightsFilters'
data_quality_flags:
items:
type: string
type: array
title: Data Quality Flags
distinct_app_count:
type: integer
minimum: 0.0
title: Distinct App Count
distinct_app_count_pct_change_vs_prev_period:
anyOf:
- type: number
- type: 'null'
title: Distinct App Count Pct Change Vs Prev Period
rows:
items:
$ref: '#/components/schemas/DesktopAppRow'
type: array
title: Rows
total_distinct_app_count:
type: integer
minimum: 0.0
title: Total Distinct App Count
type: object
required:
- filters_applied
- distinct_app_count
- rows
- total_distinct_app_count
title: DesktopAppsResponse
description: Per-app desktop dictation breakdown plus distinct-app-count headline and delta.
AiPromptQuality:
properties:
multiplier:
anyOf:
- type: number
- type: 'null'
title: Multiplier
type: object
title: AiPromptQuality
description: 'Multiplier of avg AI-prompt length vs the 8-word typed baseline (e.g. ``2.2`` renders as ``2.2x``).
Null when no AI dictations or avg words ≤ baseline.'
DesktopAppRow:
properties:
app_key:
type: string
title: App Key
category:
type: string
title: Category
word_count:
type: integer
minimum: 0.0
title: Word Count
pct_of_total:
type: number
maximum: 100.0
minimum: 0.0
title: Pct Of Total
user_count:
type: integer
minimum: 0.0
title: User Count
type: object
required:
- app_key
- category
- word_count
- pct_of_total
- user_count
title: DesktopAppRow
description: '``app_key`` is the canonical app name; display-name mapping is client-owned.'
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError
ImpactResponse:
properties:
filters_applied:
$ref: '#/components/schemas/TeamInsightsFilters'
data_quality_flags:
items:
type: string
type: array
title: Data Quality Flags
minutes_saved:
$ref: '#/components/schemas/MinutesSaved'
ai_prompt_quality:
$ref: '#/components/schemas/AiPromptQuality'
dictionary:
$ref: '#/components/schemas/DictionaryStats'
auto_formatting:
$ref: '#/components/schemas/AutoFormatting'
features_utilized:
items:
$ref: '#/components/schemas/FeatureUtilization'
type: array
title: Features Utilized
value_calculator:
$ref: '#/components/schemas/ValueCalculator'
type: object
required:
- filters_applied
- minutes_saved
- ai_prompt_quality
- dictionary
- auto_formatting
- features_utilized
- value_calculator
title: ImpactResponse
description: 'Impact-tab payload: minutes saved, prompt quality, dictionary, formatting, and ROI inputs.'
WordsDictatedTimeseries:
properties:
daily:
items:
$ref: '#/components/schemas/WordsDictatedDailyPoint'
type: array
title: Daily
weekly:
items:
$ref: '#/components/schemas/WordsDictatedWeeklyPoint'
type: array
title: Weekly
type: object
required:
- daily
- weekly
title: WordsDictatedTimeseries
description: Words-dictated series at both daily and weekly granularity.
CategoryFilterOption:
properties:
category:
type: string
title: Category
display_name:
type: string
title: Display Name
type: object
required:
- category
- display_name
title: CategoryFilterOption
description: A selectable app category in the insights filter dropdown.
FilterOptionsResponse:
properties:
teams:
items:
$ref: '#/components/schemas/TeamFilterOption'
type: array
title: Teams
apps:
items:
$ref: '#/components/schemas/AppFilterOption'
type: array
title: Apps
categories:
items:
$ref: '#/components/schemas/CategoryFilterOption'
type: array
title: Categories
type: object
required:
- teams
- apps
- categories
title: FilterOptionsResponse
description: 'Page-load filter dropdowns (teams + apps + categories).
Bundled so tab switches (Overview needs all three; Impact needs teams only)
stay on a warm cache.'
AutoFormatting:
properties:
total:
type: integer
minimum: 0.0
title: Total
by_category:
items:
$ref: '#/components/schemas/AutoFormattingCategory'
type: array
title: By Category
type: object
required:
- total
- by_category
title: AutoFormatting
description: Total auto-formatting applications with a per-category breakdown.
TeamMembersResponse:
properties:
filters_applied:
$ref: '#/components/schemas/TeamInsightsFilters'
data_quality_flags:
items:
type: string
type: array
title: Data Quality Flags
total_members:
type: integer
minimum: 0.0
title: Total Members
pct_change_vs_prev_period:
anyOf:
- type: number
- type: 'null'
title: Pct Change Vs Prev Period
mode:
type: string
enum:
- daily
- weekly
- monthly
- inactive
title: Mode
timeseries:
items:
$ref: '#/components/schemas/TeamMembersDailyPoint'
type: array
title: Timeseries
type: object
required:
- filters_applied
- total_members
- mode
- timeseries
title: TeamMembersResponse
description: 'Active-user timeseries for a single mode.
Per-day lookback: daily=1d, weekly=[D-7,D], monthly=[D-29,D], inactive=total_members-WAU.
``pct_change_vs_prev_period``: prior period picked by ``filters.comparison_mode``
when set, otherwise by shape detection. Lifetime (no ``start_date``) falls
back to L7 vs L7-L14 (or mode-matched for team-members).'
AutoFormattingCategory:
properties:
category:
type: string
title: Category
count:
type: integer
minimum: 0.0
title: Count
type: object
required:
- category
- count
title: AutoFormattingCategory
description: Auto-formatting application count for a single formatting category.
MinutesSaved:
properties:
total:
type: number
minimum: 0.0
title: Total
since:
type: string
format: date
title: Since
type: object
required:
- total
- since
title: MinutesSaved
description: '``since`` is team creation date (when team-scoped) or enterpri
# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/wispr-ai/refs/heads/main/openapi/wispr-ai-team-insights-api-openapi.yml