Projects

Create, list, fetch, and delete projects.

POST/api/v1/projects

Create Project

Create a project and start ingest. Returns 202 Accepted immediately; the project processes asynchronously via the Inngest pipeline.

Cloud import (source_type cloud) is Pro only. Requires Google Drive, Dropbox, or OneDrive connected under Settings → Integrations. SparkVox downloads or exports the file server-side and starts ingest in one request. Supported via API: MP3 (up to 500 MB) and SRT on google-drive, dropbox, and onedrive; native Google Docs on google-drive only (mime_type application/vnd.google-apps.document, exported to plain text). Plain text transcripts use source_type transcript. The web app Import from cloud tab also supports TXT on all providers.

Notetaker import (source_type notetaker) is Pro, Accelerate, or Scale only. Requires Fireflies, Fathom, Granola, Google Meet, or Zoom connected under Settings → Integrations. SparkVox fetches the transcript server-side and starts ingest in one request. List meetings with GET/api/v1/notetaker-meetings.

Request body

URL source

json
{
  "title": "My Podcast Episode",
  "source_type": "url",
  "source_url": "https://youtube.com/watch?v=...",
  "transcript": null,
  "source_material": "Podcast / Interview",
  "perspective": "host",
  "platforms": ["linkedin"],
  "duration_seconds": 3600
}

Cloud source (Google Drive, Dropbox, or OneDrive)

json
{
  "title": "Drive episode",
  "source_type": "cloud",
  "source_material": "Podcast / Interview",
  "perspective": "host",
  "platforms": ["linkedin"],
  "duration_seconds": 3600,
  "provider": "google-drive",
  "file_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
  "file_name": "episode.mp3",
  "mime_type": "audio/mpeg",
  "size": 8000000
}

file_id is the provider file identifier (from Google Drive, Dropbox, or OneDrive). size is optional but recommended for MP3 billing checks.

Google Doc on Google Drive

json
{
  "title": "Workshop notes doc",
  "source_type": "cloud",
  "source_material": "Knowledge & Advisory",
  "perspective": "trainer",
  "platforms": ["linkedin"],
  "duration_seconds": 1800,
  "provider": "google-drive",
  "file_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
  "file_name": "Q3 workshop notes",
  "mime_type": "application/vnd.google-apps.document"
}

Google Docs are google-drive only. SparkVox exports the Doc to text and skips audio transcription. duration_seconds is required for billing - estimate from document length (for example word count at a typical speaking pace) the same way you would for a pasted transcript project.

Notetaker source (Fireflies, Fathom, Granola, Google Meet, Zoom)

json
{
  "title": "Client discovery call",
  "source_type": "notetaker",
  "source_material": "Knowledge & Advisory",
  "perspective": "advisor",
  "platforms": ["linkedin"],
  "duration_seconds": 2700,
  "provider": "granola",
  "meeting_id": "not_1d3tmYTlCICgjy"
}

meeting_id comes from GET/api/v1/notetaker-meetings. Connect the notetaker in the app before using the API.

Fields

FieldRequiredNotes
titleYesDisplay name for the project
source_typeYesurl, transcript, cloud, or notetaker (device upload not supported in v1)
source_urlFor urlPublic audio/video URL (YouTube supported)
transcriptFor transcriptFull transcript text; skips transcription
providerFor cloud or notetakerCloud: google-drive, dropbox, or onedrive. Notetaker: fireflies, fathom, granola, google-meet, or zoom
file_idFor cloudProvider file ID
meeting_idFor notetakerMeeting or note id from GET/api/v1/notetaker-meetings
file_nameFor cloudOriginal filename (used for type detection)
mime_typeFor cloudaudio/mpeg (MP3), application/x-subrip or text/srt (SRT), application/vnd.google-apps.document (Google Docs on google-drive only)
sizeFor cloudFile size in bytes (optional; recommended for MP3)
source_materialNoPodcast / Interview or Knowledge & Advisory. Omitted → API key owner's onboarding default, then Podcast / Interview
perspectiveNoPerspective slug (see below). Omitted → owner's Settings → Project Presets defaults from profiles.onboarding
platformsNoArray - only linkedin is live today; others are stripped
duration_secondsYesContent length in seconds - used for billing

Source material and perspective (slugs)

Projects store a source lens on each row: source_material (Podcast / Interview or Knowledge & Advisory) and professional_perspective (a slug). POST/api/v1/projects accepts slugs only in perspective. Legacy pipeline ids thought_leader, expert_guest, and show_brand return 400.

Source materialValid perspective slugsIngest behavior
Podcast / Interviewhost, guest, full_conversationhost / guest → diarized + speaker pick; full_conversation → full transcript
Knowledge & Advisoryexpert, advisor, trainerexpert / advisor → diarized + speaker pick; trainer → full transcript

Slug must match source_material (e.g. trainer with Podcast / Interview returns 400). Multi-speaker recordings with host, guest, or advisor may pause at awaiting_speaker until the user selects their speaker in the app (API clients should poll GET/projects/:id).

Response 202

json
{ "project_id": "uuid", "status": "pending" }

Error responses

  • 400 - missing/invalid fields, invalid perspective, unsupported source_type
  • 401 - invalid or missing API key
  • 402 - insufficient processing time (error body may say Insufficient credits.)
  • 429 - rate limit exceeded
GET/api/v1/projects

List Projects

List projects for the authenticated API key owner.

Query parameters

  • limit - max results (default 50, max 100)
  • offset - pagination offset (default 0)

Response 200

json
{
  "projects": [
    {
      "id": "uuid",
      "title": "My Episode",
      "status": "ready",
      "source_type": "url",
      "platforms": ["linkedin"],
      "created_at": "2026-05-01T10:00:00Z",
      "processing_cost_cents": 5400,
      "error_message": null
    }
  ]
}

Project statuses: pending → transcribing → (awaiting_speaker?) → extracting → generating → ready | failed. awaiting_speaker appears when diarization completes and the user must pick their speaker in the app before generation continues.

GET/api/v1/projects/:id

Get Project

Fetch a single project by ID. Returns 404 if not found or not owned by the API key user.

Response 200

json
{
  "project": {
    "id": "uuid",
    "title": "...",
    "status": "ready",
    "source_type": "url",
    "platforms": ["linkedin"],
    "duration_seconds": 3600,
    "created_at": "...",
    "processing_cost_cents": 5400,
    "error_message": null
  }
}
DELETE/api/v1/projects/:id

Delete Project

Permanently delete a project and all associated moments and posts. Raw audio in R2 is removed when present.

Response 200

json
{ "deleted": true }