Openwhispr ApiSAFE
Voice-to-text dictation app with local (Nvidia Parakeet/Whisper) and cloud models (BYOK). Privacy-first and available cross-platform.
Overview
Voice-to-text dictation app with local (Nvidia Parakeet/Whisper) and cloud models (BYOK). Privacy-first and available cross-platform.
0d40a92647a7OBSERVED · 2026-10-07Install
Commands as the repository documents them. They are shown, not run.
claude mcp add openwhispr --transport http https://mcp.openwhispr.com/mcp \
Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: openwhispr-api
description: Use this skill when building integrations with the OpenWhispr REST API, calling OpenWhispr endpoints, managing notes/folders/transcriptions programmatically, accessing team-space content with workspace keys, or connecting to the OpenWhispr MCP server. Covers authentication, all V1 endpoints, spaces, pagination, rate limits, error handling, and the remote MCP server.
---
# OpenWhispr API v1
Use this reference when making requests to the OpenWhispr REST API. All endpoints are under the V1 path and require API key authentication.
## Authentication
Pass the API key as a Bearer token in the `Authorization` header on every request.
```
Authorization: Bearer owk_live_YOUR_KEY
```
There are two kinds of key:
- **Personal keys** (`owk_live_`) — access your own private notes, folders, and transcriptions. Generated under **Settings > API Keys**.
- **Workspace keys** (`ow_wks_live_`) — access a workspace's **team spaces**. Generated by a workspace admin under **Settings > Workspace > Developer**.
Both are shown once at creation.
### Scopes
Each key has scoped permissions. The API rejects requests missing the required scope with `403 Forbidden`.
**Personal key scopes:**
| Scope | Grants |
| --------------------- | ------------------------------------------------- |
| `notes:read` | List, get, and search notes. List folders. |
| `notes:write` | Create, update, and delete notes. Create folders. |
| `transcriptions:read` | List and get transcriptions. |
| `usage:read` | Read usage statistics. |
**Workspace key scopes:**
| Scope | Grants |
| ------------------------------- | ------------------------------------------------------------------------------- |
| `workspace:notes:read` | List, get, and search team-space notes. |
| `workspace:notes:write` | Create, update, and delete team-space notes. |
| `workspace:folders:read` | List team-space folders. |
| `workspace:folders:write` | Create team-space folders. |
| `workspace:transcriptions:read` | Space discovery only for now — no transcription endpoints accept workspace keys yet. |
| `workspace:*` | All of the above (admin). |
Any of the content scopes above also grants `GET /spaces/list` (space discovery).
### Team spaces
A **space** is a shared container of notes and folders inside a workspace. Personal keys never see team-space content; **workspace keys** do, and always address one space at a time via a `space_id`:
- Discover the spaces a key can reach with `GET /spaces/list`.
- `list`, `create`, and `search` for notes and folders **require** a `space_id` (query param or body field) when called with a workspace key, and reject one when called with a personal key.
- Operations addressed by note id (`GET/PATCH/DELETE /notes/{id}`, `GET /notes/{id}/transcript`) resolve the note's space automatically — no `space_id` needed. A workspace key may act on any note in any of its workspace's spaces.
- `space_id` cannot be changed through the API — a note stays in the space it was created in. Move notes between spaces from the desktop app.
## Base URL
```
https://api.openwhispr.com/api/v1
```
## Response Envelope
Wrap all responses in a consistent envelope.
**Single resource:**
```json
{ "data": { "id": "uuid", "title": "My note", ... } }
```
**Paginated list:**
```json
{
"data": [{ ... }, { ... }],
"has_more": true,
"next_cursor": "opaque-cursor-string"
}
```
**Error:**
```json
{ "error": { "code": "not_found", "message": "Note not found" } }
```
### Error Codes
| HTTP Status | Code | Meaning |
| ----------- | -------------------- | -------------------------------------------------- |
| 400 | `validation_error` | Invalid request body or query params |
| 401 | `invalid_api_key` | Missing, malformed, expired, or revoked key |
| 403 | `forbidden` | Key lacks required scope |
| 404 | `not_found` | Resource does not exist or belongs to another user |
| 405 | `method_not_allowed` | Wrong HTTP method |
| 409 | `conflict` | Duplicate resource (e.g. folder name) |
| 429 | `rate_limited` | Rate limit exceeded — check `Retry-After` header |
| 500 | `internal_error` | Server error |
## Rate Limits
Enforced per API key with minute and daily windows. Search requests cost 5x against the rate limit.
| Plan | Per Minute | Per Day |
| -------- | ---------- | ------- |
| Free | 30 | 1,000 |
| Pro | 120 | 10,000 |
| Business | 300 | 50,000 |
Response headers on every request:
| Header | Description |
| ----------------------- | --------------------------------- |
| `X-RateLimit-Limit` | Max requests per minute |
| `X-RateLimit-Remaining` | Remaining in current window |
| `X-RateLimit-Reset` | Unix timestamp when window resets |
| `Retry-After` | Seconds to wait (only on 429) |
## Pagination
List endpoints use cursor-based pagination. Treat `next_cursor` as an **opaque string**: pass it back verbatim as the `cursor` query parameter to fetch the next page — never parse it. (Notes cursors are base64url-encoded composites; transcription cursors are timestamps. Timestamp cursors issued beTrust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
0d40a92647a7full audit observations/trust-audit/skill/openwhispr__openwhispr-api.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-07 | 0d40a92647a7 | SAFE | B | 89 | first audit |
Questions
What does the Openwhispr Api skill do?
Voice-to-text dictation app with local (Nvidia Parakeet/Whisper) and cloud models (BYOK). Privacy-first and available cross-platform.
Is Openwhispr Api safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Openwhispr Api access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
What do I need installed to use Openwhispr Api?
Its own instructions reference space_id. Dependencies are pinned to exact versions.
Which assistants does Openwhispr Api work with?
Its documentation mentions claude-code and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (0d40a92647a7), read on 2026-10-07. The repository is watched, and a new audit runs when it changes — this is the first audit.