Jobs
Run and manage background import, retranscription, and diarization jobs, and wait for them to finish.
Jobs are background tasks. There are three kinds: import, retranscription, and diarization. A job moves through states and ends in completed, failed, or cancelled. Submitting a job returns a job id immediately; you then poll the job list or block on the wait stream.
Endpoints
| Method + path | Scope | Notes |
|---|---|---|
GET /v1/jobs | Read | List jobs. Returns each job's id, kind, state, stage, progress, meeting id, and error if any. |
GET /v1/jobs/:id | Read | Get one job. |
POST /v1/jobs/diarization | Write | Submit a re-diarization for a meeting. Body {meeting_id, speaker_count?}. A re-run conflict returns 409. |
POST /v1/jobs/import | Write | Import an audio file. See Import an audio file below. |
POST /v1/jobs/:id/cancel | Write | Cancels a running job. |
POST /v1/jobs/:id/pause | Write | Pauses a running job. |
POST /v1/jobs/:id/resume | Write | Resumes a paused job. |
POST /v1/jobs/:id/retry | Write | Retries a failed job. |
GET /v1/jobs/:id/wait | Read | One-shot SSE. Resolves when the job reaches completed, failed, or cancelled. Default 300 seconds, capped at 3600 seconds. |
Job error text is path-redacted
A failed import, retranscription, or diarization job has its error field redacted before it's returned from GET /v1/jobs and GET /v1/jobs/:id: a home folder collapses to ~ with the username dropped, and other absolute paths reduce to just the filename. It's safe to surface this text directly.
Import an audio file
POST /v1/jobs/import takes a query param filename and the raw audio bytes as the request body. There is deliberately no source-path parameter; the server reads bytes, not a path on disk.
Limits:
| Limit | Value |
|---|---|
| Max size per upload | 2 GB |
| Max total across imports | 20 GB |
| Max concurrent imports | 3 |
| Estimated decoded-memory ceiling | 4 GB |
Accepted formats: mp4, m4a, wav, mp3, flac, ogg, aac, mkv, webm, wma.
The call returns 202 with a job_id. Poll GET /v1/jobs/:id to watch progress and to read the resulting meeting_id once it is assigned.
Import jobs cannot be paused or resumed: a pause returns 409 import_not_pausable. Retrying an import whose uploaded bytes are gone returns 409 source_gone.
curl -s -X POST "http://127.0.0.1:8420/v1/jobs/import?filename=standup.m4a" -H "Authorization: Bearer $MEETILY_PRO_TOKEN" --data-binary @standup.m4aNo CLI, SDK, or MCP for import
Import is HTTP only. There is no CLI command, no Python SDK method, and no MCP tool for it.
Retranscription
Retranscription has no submit route of its own. It is reached only by retrying an existing desktop-created transcription job with POST /v1/jobs/:id/retry.
Client exposure by capability
| Capability | How to call |
|---|---|
| Import | HTTP only (no CLI command, no SDK method, no MCP tool) |
| Get one job | HTTP and the MCP get_job tool (no CLI, no SDK method) |
| Wait | HTTP, the Python SDK jobs.wait(), and the MCP wait tool (no CLI) |
| Diarization | HTTP, CLI (meetily-pro jobs diarization), SDK, and MCP |
Submit a diarization job
curl -s -X POST http://127.0.0.1:8420/v1/jobs/diarization -H "Authorization: Bearer $MEETILY_PRO_TOKEN" -H "content-type: application/json" -d '{"meeting_id":"MEETING_ID","speaker_count":3}'meetily-pro jobs diarization --meeting-id MEETING_ID --speaker-count 3from meetily_agent import MeetilyClient
print(MeetilyClient().jobs.diarization("MEETING_ID", speaker_count=3))Diarization reruns can conflict
Submitting a diarization job while one is already running for the same meeting returns 409. Wait for the running job to finish, or check the job list first.
List jobs
curl -s http://127.0.0.1:8420/v1/jobs -H "Authorization: Bearer $MEETILY_PRO_TOKEN"meetily-pro jobs listfrom meetily_agent import MeetilyClient
print(MeetilyClient().jobs.list())Wait for a job
The wait endpoint is a one-shot SSE stream. It yields exactly one terminal event, then closes the connection. The stream is burst-safe: even if a flood of events briefly outpaces it, it resolves on the terminal state that was actually reached rather than falsely reporting a timeout. Only job.completed, job.failed, and job.cancelled are terminal; pause and resume never resolve it.
curl -N -s "http://127.0.0.1:8420/v1/jobs/JOB_ID/wait?timeout=300" -H "Authorization: Bearer $MEETILY_PRO_TOKEN"# No CLI command for the wait stream yet - use curl or the Python SDK.from meetily_agent import MeetilyClient
event, data = MeetilyClient().jobs.wait("JOB_ID", timeout=300)Observe pause and resume
Pausing or resuming a job also emits an observable event, job.paused and job.resumed (read scope), which you can receive over a webhook or watch on the event bus. They are status events, not terminal ones, so they never resolve a job wait. A single pause may deliver job.paused up to twice (once as pausing begins, once when it settles); both carry the same job id. See Events and SSE.
Last updated on
