API reference

Early access. Capvo is rolling out gradually. API access is enabled for early-access accounts as they come onboard — join the waitlist to get yours.

The Capvo REST API lets you read your transcripts, search across meetings, and manage webhook endpoints. Base URL:

https://api.capvo.app

All requests require an API key. All responses are JSON. All timestamps are ISO 8601 in UTC.

Authentication

Send your API key as a Bearer token in the Authorization header.

curl https://api.capvo.app/v1/notes \
  -H "Authorization: Bearer cpv_your_key"

API keys are scoped to your account. They're stored bcrypt-hashed on the server, so we never have access to the plaintext after creation. Lost keys cannot be recovered; revoke and create a new one.

Every key is limited to 100 requests per minute, on every plan. When rate-limited you receive 429 Too Many Requests with a Retry-After header.


List notes

Returns a paginated list of your recorded meetings, newest first.

GET /v1/notes

Parameters

ParameterTypeDescription
limitintegerMax results, default 20, max 100.
cursorstringThe next_cursor value returned by the previous page.
platformstringFilter: meet, zoom, teams, phone.
created_afterdatetimeISO 8601. Inclusive lower bound on created_at.
created_beforedatetimeISO 8601. Inclusive upper bound on created_at.

Example

curl "https://api.capvo.app/v1/notes?limit=20&platform=meet" \
  -H "Authorization: Bearer cpv_your_key"
{
  "data": [
    {
      "id": "fd1c2b0e-08a2-4ee0-ab26-9f3a7a14b2c1",
      "title": "Q2 Revenue Review",
      "platform": "meet",
      "duration_seconds": 1842,
      "started_at": "2026-04-27T14:02:11Z",
      "ended_at": "2026-04-27T14:32:53Z",
      "status": "ready",
      "transcript": [
        { "sequence": 1, "speaker": "Albert", "content": "Let's start with the numbers.", "start_time": 4.2, "end_time": 8.9 },
        { "sequence": 2, "speaker": "Maya", "content": "Revenue is up 18% quarter over quarter.", "start_time": 9.1, "end_time": 13.4 }
      ],
      "summary": {
        "context": "Quarterly revenue review with finance.",
        "decisions": ["Ship the updated forecast this week"],
        "action_items": [{ "task": "Send updated forecast to finance", "owner": "Albert", "deadline": null }],
        "participants": ["Albert", "Maya"],
        "next_step": "Forecast review on Friday",
        "budget_mentioned": null,
        "sentiment": "positive"
      }
    }
  ],
  "next_cursor": "2026-04-27T14:02:11Z",
  "has_more": true
}

Each note id is a UUID v4. The transcript array is included inline; there is no separate transcript_url. summary is null until the AI summary has been generated for that meeting.

TypeScript

interface NotesListResponse {
  data: Note[]
  next_cursor: string | null
  has_more: boolean
}
 
interface Note {
  id: string // UUID v4
  title: string | null
  platform: 'meet' | 'zoom' | 'teams' | 'phone'
  duration_seconds: number
  started_at: string
  ended_at: string
  status: string
  transcript: TranscriptSegment[]
  summary: Summary | null
}
 
interface TranscriptSegment {
  sequence: number // 1-indexed segment order
  speaker: string
  content: string
  start_time: number // seconds from start of recording
  end_time: number | null
}
 
interface Summary {
  context: string | null
  decisions: string[]
  action_items: Array<{ task: string; owner: string | null; deadline: string | null }>
  participants: string[]
  next_step: string | null
  budget_mentioned: string | null
  sentiment: string | null
}

Get a note

Returns a single meeting with its full transcript.

GET /v1/notes/:id

Example

curl https://api.capvo.app/v1/notes/fd1c2b0e-08a2-4ee0-ab26-9f3a7a14b2c1 \
  -H "Authorization: Bearer cpv_your_key"

The response is a single Note object — the same shape as the entries in List notes. A note that does not exist (or belongs to another account) returns 404.

To delete a meeting and its transcript, use the desktop app (the meeting's ⋯ menu → Delete). Deletion via the API is not available yet.


Search notes

Semantic search across the meetings you own. The query is embedded and matched against meeting summaries by similarity, so it finds meaning, not just keywords.

GET /v1/notes/search?q=...

Parameters

ParameterTypeDescription
qstringRequired. The natural-language search query.
limitintegerMax results, default 5, max 20.

Example

curl "https://api.capvo.app/v1/notes/search?q=budget+approval" \
  -H "Authorization: Bearer cpv_your_key"
{
  "data": [
    {
      "id": "fd1c2b0e-08a2-4ee0-ab26-9f3a7a14b2c1",
      "title": "Q2 Revenue Review",
      "platform": "meet",
      "duration_seconds": 1842,
      "started_at": "2026-04-27T14:02:11Z",
      "ended_at": "2026-04-27T14:32:53Z",
      "status": "ready",
      "transcript": [
        { "sequence": 1, "speaker": "Albert", "content": "Let's start with the numbers.", "start_time": 4.2, "end_time": 8.9 }
      ],
      "summary": null
    }
  ]
}

Results are full Note objects, ranked by relevance, transcript included — no second request needed.


Manage webhooks

Webhook endpoints can be created from the desktop app or via the API.

Create endpoint

POST /v1/webhooks
curl https://api.capvo.app/v1/webhooks \
  -H "Authorization: Bearer cpv_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/capvo",
    "events": ["meeting.transcribed", "summary.ready"]
  }'
{
  "id": "b7a9c4d2-1f3e-4a8b-9c5d-6e2f8a3b1c4d",
  "url": "https://example.com/capvo",
  "events": ["meeting.transcribed", "summary.ready"],
  "active": true,
  "created_at": "2026-04-27T14:02:11Z",
  "secret": "8f3a1c9e2b7d4f6a0c5e8b1d3f7a2c4e6b9d1f3a5c7e0b2d4f6a8c1e3b5d7f9a"
}

The endpoint id is a UUID v4. events defaults to ["meeting.completed"] when omitted. The endpoint URL must be https:// and publicly reachable — addresses that resolve to private networks are rejected.

The secret is shown once. Use it to verify the HMAC signature on incoming webhooks. See HMAC verification.

List endpoints

GET /v1/webhooks

Returns all active and inactive webhook endpoints for your account. Secrets are not returned; you receive them only when an endpoint is created.

Delete an endpoint

DELETE /v1/webhooks/:id

Removes the endpoint immediately and returns { "success": true }.

Delivery history

GET /v1/webhooks/:id/deliveries

Paginated log of every delivery attempt to an endpoint (newest first), including the event name, HTTP status code your endpoint returned, the attempt number, and the payload. Use it to debug failed deliveries without leaving your terminal.

ParameterTypeDescription
limitintegerMax results, default 25, max 100.
cursorstringThe next_cursor value from the previous page.

Error codes

All errors return a JSON body with an error message:

{
  "error": "Note not found"
}
HTTPMeaning
400Required parameters are missing or malformed.
401The API key is missing, invalid, or revoked.
404The resource does not exist or is not visible to your key.
429You have exceeded the rate limit (100 req/min). Honor Retry-After.
500Something broke on our side. The request can be safely retried.