audivo-dev · Schema

JobStatus

Failure/cancellation objects report `reservation_released: true` and never imply a cash refund occurred — a cash refund is a separate, explicit Stripe refund via `POST /v1/billing/refund`.

CompanyPodcastTranscriptsAPIAudio

Properties

Name Type Description
job_id object
status object
episode_id object
show_title object
episode_title object
progress object
estimated_credits object
reserved_credits object
settled_credits object Present on terminal `completed` jobs; measured usage capped at the reservation.
released_credits object Present on terminal states; the unused portion of the reservation released back to the account.
reservation_released boolean Present on terminal `failed`/`cancelled` jobs. Never implies a cash refund.
ledger_event_ids array Immutable ledger event IDs, present on terminal states.
error object Present when `status` is `failed`; code `processing_failed` with retryability metadata.
artifact object The completed transcript, in JSON delivery. Present only when `status` is `completed` **and** the caller explicitly asked for it with `?format=json` on `GET /v1/transcripts/{job_id}` — `PollFormatQuer
created_at string
started_at string
completed_at string
View JSON Schema on GitHub

JSON Schema

audivo-dev-job-status-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/audivo-dev/json-schema/audivo-dev-job-status-schema.json",
  "title": "JobStatus",
  "description": "Failure/cancellation objects report `reservation_released: true` and never imply a cash refund occurred — a cash refund is a separate, explicit Stripe refund via `POST /v1/billing/refund`.",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/audivo-dev-openapi.yaml#/components/schemas/JobStatus",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "job_id",
    "status",
    "episode_id",
    "show_title",
    "episode_title",
    "estimated_credits",
    "reserved_credits",
    "created_at"
  ],
  "properties": {
    "job_id": {
      "$ref": "#/$defs/JobId"
    },
    "status": {
      "$ref": "#/$defs/JobState"
    },
    "episode_id": {
      "$ref": "#/$defs/EpisodeId"
    },
    "show_title": {
      "$ref": "#/$defs/JobShowTitle"
    },
    "episode_title": {
      "$ref": "#/$defs/JobEpisodeTitle"
    },
    "progress": {
      "$ref": "#/$defs/JobProgress"
    },
    "estimated_credits": {
      "$ref": "#/$defs/CreditAmount"
    },
    "reserved_credits": {
      "$ref": "#/$defs/CreditAmount"
    },
    "settled_credits": {
      "$ref": "#/$defs/CreditAmount",
      "description": "Present on terminal `completed` jobs; measured usage capped at the reservation."
    },
    "released_credits": {
      "$ref": "#/$defs/CreditAmount",
      "description": "Present on terminal states; the unused portion of the reservation released back to the account."
    },
    "reservation_released": {
      "type": "boolean",
      "description": "Present on terminal `failed`/`cancelled` jobs. Never implies a cash refund."
    },
    "ledger_event_ids": {
      "type": "array",
      "maxItems": 20,
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 80
      },
      "description": "Immutable ledger event IDs, present on terminal states."
    },
    "error": {
      "$ref": "#/$defs/ErrorDetail",
      "description": "Present when `status` is `failed`; code `processing_failed` with retryability metadata."
    },
    "artifact": {
      "$ref": "#/$defs/TranscriptArtifact",
      "description": "The completed transcript, in JSON delivery. Present only when `status` is `completed` **and** the caller explicitly asked for it with `?format=json` on `GET /v1/transcripts/{job_id}` — `PollFormatQueryParam` has no default, so omitting `format` there is a real, distinct request that never carries `artifact`, whatever `status` is. It is deliberately *not* required by `completed`: a client polling a finished job would otherwise be forced to re-download the whole transcript on every call, with no status-only option."
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "started_at": {
      "type": "string",
      "format": "date-time"
    },
    "completed_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "allOf": [
    {
      "if": {
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "const": "failed"
          }
        }
      },
      "then": {
        "required": [
          "reservation_released",
          "released_credits",
          "error"
        ]
      },
      "else": {
        "not": {
          "required": [
            "error"
          ]
        }
      }
    },
    {
      "if": {
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "const": "cancelled"
          }
        }
      },
      "then": {
        "required": [
          "reservation_released",
          "released_credits"
        ]
      }
    },
    {
      "if": {
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "enum": [
              "failed",
              "cancelled"
            ]
          }
        }
      },
      "else": {
        "not": {
          "required": [
            "reservation_released"
          ]
        }
      }
    },
    {
      "if": {
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "const": "completed"
          }
        }
      },
      "then": {
        "required": [
          "settled_credits",
          "released_credits"
        ]
      },
      "else": {
        "allOf": [
          {
            "not": {
              "required": [
                "settled_credits"
              ]
            }
          },
          {
            "not": {
              "required": [
                "artifact"
              ]
            }
          }
        ]
      }
    },
    {
      "if": {
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "enum": [
              "completed",
              "failed",
              "cancelled"
            ]
          }
        }
      },
      "else": {
        "allOf": [
          {
            "not": {
              "required": [
                "released_credits"
              ]
            }
          },
          {
            "not": {
              "required": [
                "ledger_event_ids"
              ]
            }
          }
        ]
      }
    }
  ],
  "$defs": {
    "CanonicalTranscript": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "episode_id",
        "show_id",
        "language",
        "duration_sec",
        "source",
        "source_revision",
        "model_version",
        "pipeline_version",
        "timing_precision",
        "diarized",
        "warnings",
        "segments",
        "created_at"
      ],
      "properties": {
        "episode_id": {
          "$ref": "#/$defs/EpisodeId"
        },
        "show_id": {
          "$ref": "#/$defs/ShowId"
        },
        "language": {
          "$ref": "#/$defs/Language",
          "description": "Resolved BCP-47 language code."
        },
        "duration_sec": {
          "type": "number",
          "minimum": 0,
          "maximum": 129600
        },
        "source": {
          "$ref": "#/$defs/TranscriptSource"
        },
        "source_revision": {
          "type": "string",
          "minLength": 1,
          "maxLength": 150,
          "description": "e.g. `sha256:...` — the asset revision this transcript was produced from."
        },
        "model_version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "Provider-pinned model version, or `publisher` for passthrough."
        },
        "pipeline_version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60
        },
        "timing_precision": {
          "$ref": "#/$defs/TimingPrecision"
        },
        "diarized": {
          "const": false,
          "description": "Always `false` in the MVP; diarization is post-MVP."
        },
        "warnings": {
          "type": "array",
          "maxItems": 1000,
          "items": {
            "$ref": "#/$defs/TranscriptWarning"
          }
        },
        "segments": {
          "type": "array",
          "maxItems": 200000,
          "items": {
            "$ref": "#/$defs/TranscriptSegment"
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "CreditAmount": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991,
      "description": "A non-negative JavaScript-safe integer credit amount. The upper bound matches `Number.MAX_SAFE_INTEGER`, which is enforced by the domain ledger so arithmetic and JSON round-trips cannot silently lose cents worth of credit precision."
    },
    "EpisodeId": {
      "type": "string",
      "pattern": "^ep_[a-z2-7]{16}$",
      "description": "Canonical episode identifier."
    },
    "ErrorCode": {
      "type": "string",
      "enum": [
        "invalid_request",
        "invalid_url",
        "unauthenticated",
        "idempotency_conflict",
        "job_not_completed",
        "source_not_supported",
        "feed_dead",
        "episode_not_found",
        "show_not_found",
        "unsafe_source",
        "unsupported_codec",
        "unsupported_language",
        "duration_exceeded",
        "size_exceeded",
        "content_blocked",
        "payment_required",
        "rate_limited",
        "concurrency_limited",
        "job_not_found",
        "api_key_not_found",
        "api_key_limit_reached",
        "credit_lot_not_found",
        "credits_not_refundable",
        "engine_unavailable",
        "processing_failed",
        "discovery_unavailable",
        "nothing_to_quote",
        "internal_error",
        "quote_not_found",
        "group_not_found",
        "quote_expired",
        "quote_mismatch",
        "quote_unverified",
        "expected_total_mismatch",
        "request_in_progress",
        "account_suspended",
        "account_closed",
        "account_not_found",
        "tier_unchanged",
        "upload_quota_exceeded",
        "upload_not_found",
        "upload_not_received",
        "upload_mismatch",
        "max_credits_exceeded",
        "oauth_request_not_found",
        "connected_app_not_found"
      ],
      "description": "Every code the API returns, and the HTTP status it comes with. `invalid_request`, `invalid_url` → 400. `unauthenticated` → 401. `payment_required` → 402. `job_not_found`, `quote_not_found`, `group_not_found`, `api_key_not_found`, `credit_lot_not_found`, `upload_not_found`, `oauth_request_not_found`, `connected_app_not_found` → 404. `idempotency_conflict`, `request_in_progress`, `job_not_completed`, `quote_expired`, `quote_mismatch`, `quote_unverified`, `expected_total_mismatch`, `account_suspended`, `account_closed`, `account_not_found`, `api_key_limit_reached`, `tier_unchanged`, `upload_not_received` → 409; `upload_not_received` is retryable once the file's PUT has landed. `source_not_supported`, `feed_dead`, `episode_not_found`, `show_not_found`, `unsafe_source`, `unsupported_codec`, `unsupported_language`, `duration_exceeded`, `size_exceeded`, `nothing_to_quote`, `credits_not_refundable`, `upload_mismatch`, `max_credits_exceeded` → 422. `content_blocked` → 451. `rate_limited`, `concurrency_limited`, `upload_quota_exceeded` → 429; `upload_quota_exceeded` is retryable, at the earliest capacity return time its message names. `internal_error`, `processing_failed` → 500. `discovery_unavailable`, `engine_unavailable` → 503. `processing_failed` also appears inside a failed job's `error` field rather than as a live status. Each code has a heading on the documentation site's errors page, which is what `doc_url` links to."
    },
    "ErrorDetail": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "type",
        "code",
        "message",
        "doc_url",
        "request_id",
        "retryable"
      ],
      "properties": {
        "type": {
          "$ref": "#/$defs/ErrorType"
        },
        "code": {
          "$ref": "#/$defs/ErrorCode"
        },
        "message": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1000
        },
        "doc_url": {
          "type": "string",
          "format": "uri",
          "maxLength": 300
        },
        "request_id": {
          "$ref": "#/$defs/RequestId"
        },
        "retryable": {
          "type": "boolean"
        }
      },
      "oneOf": [
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "enum": [
                "invalid_request",
                "invalid_url",
                "source_not_supported",
                "unsafe_source"
              ]
            },
            "type": {
              "const": "invalid_request"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "enum": [
                "duration_exceeded",
                "size_exceeded",
                "unsupported_codec",
                "unsupported_language",
                "credits_not_refundable",
                "upload_mismatch",
                "max_credits_exceeded"
              ]
            },
            "type": {
              "const": "unprocessable_input"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "const": "unauthenticated"
            },
            "type": {
              "const": "unauthenticated"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "enum": [
                "idempotency_conflict",
                "job_not_completed",
                "quote_expired",
                "quote_mismatch",
                "quote_unverified",
                "expected_total_mismatch",
                "request_in_progress",
                "account_suspended",
                "account_closed",
                "account_not_found",
                "api_key_limit_reached",
                "tier_unchanged",
                "upload_not_received"
              ]
            },
            "type": {
              "const": "conflict"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "enum": [
                "feed_dead",
                "episode_not_found",
                "show_not_found",
                "job_not_found",
                "quote_not_found",
                "group_not_found",
                "api_key_not_found",
                "credit_lot_not_found",
                "upload_not_found",
                "oauth_request_not_found",
                "connected_app_not_found"
              ]
            },
            "type": {
              "const": "not_found"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "const": "content_blocked"
            },
            "type": {
              "const": "content_blocked"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "const": "payment_required"
            },
            "type": {
              "const": "payment_required"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "enum": [
                "rate_limited",
                "concurrency_limited",
                "upload_quota_exceeded"
              ]
            },
            "type": {
              "const": "rate_limited"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "enum": [
                "engine_unavailable",
                "processing_failed",
                "discovery_unavailable",
                "internal_error"
              ]
            },
            "type": {
              "const": "unavailable"
            }
          }
        },
        {
          "required": [
            "code",
            "type"
          ],
          "properties": {
            "code": {
              "const": "nothing_to_quote"
            },
            "type": {
              "const": "unprocessable_input"
            }
          }
        }
      ]
    },
    "ErrorType": {
      "type": "string",
      "enum": [
        "invalid_request",
        "unprocessable_input",
        "unauthenticated",
        "conflict",
        "not_found",
        "content_blocked",
        "payment_required",
        "rate_limited",
        "unavailable"
      ],
      "description": "The family an error belongs to, for handling; `code` is the precise reason. `invalid_request`: something in the request is wrong — fix the integration. `unprocessable_input`: the request is well-formed but the episode or resource is outside published support. `unauthenticated`: missing, malformed, revoked or expired credential. `payment_required`: the account's credits cannot cover the ceiling. `conflict`: the resource's or the account's state refuses this request as sent — a lapsed quote, a reused idempotency key, a held account. `not_found`: the job, quote, group or key the request named does not exist for this account. `rate_limited`: over a plan limit; wait and retry. `unavailable`: a failure on our side or at a provider; retry, and quote `request_id` if it persists."
    },
    "EstimatedProcessingSeconds": {
      "type": "integer",
      "minimum": 0,
      "maximum": 72000,
      "description": "Estimated **wall-clock** seconds until the job reaches a terminal state — intended for choosing a poll interval. This is *not* audio duration: audio duration has its own field (`duration_sec` on the transcript, `duration_sec` on `EpisodeSummary`), and conflating the two silently misprices everything a caller derives from it. The committed examples only make sense under this reading: `estimated_seconds: 420` alongside `estimated_credits: 268` cannot be audio seconds, because 7 audio minutes bills 7 credits at `CREDITS_PER_AUDIO_MINUTE`, while 268 credits is about 4.5 hours of audio.\n\nThe bound is derived from that meaning rather than copied from the audio cap: twice the published 10-hour `max_audio_duration_seconds` ceiling, an end-to-end envelope that still holds at a pathological 1× realtime factor. The real hard per-job timeout is duration-scaled and much shorter."
    },
    "JobEpisodeTitle": {
      "description": "The episode's title as it was when this job or read was created, or `null` when it was created without one. For an upload it is the title given when the file was announced. Where a feed gave no title, a catalog read (`GET /v1/episodes/{episode_id}/transcript`) answers the identifier the catalog stores in its place.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1,
          "maxLength": 300
        },
        {
          "type": "null"
        }
      ]
    },
    "JobId": {
      "type": "string",
      "pattern": "^job_[A-Za-z0-9]{16,32}$",
      "maxLength": 40,
      "description": "Opaque, server-generated job identifier."
    },
    "JobProgress": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "chunks_done",
        "chunks_total",
        "percent",
        "realtime_factor",
        "eta_seconds"
      ],
      "properties": {
        "chunks_done": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000
        },
        "chunks_total": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000
        },
        "percent": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        },
        "realtime_factor": {
          "type": "number",
          "minimum": 0,
          "maximum": 10000
        },
        "eta_seconds": {
          "description": "Estimated wall-clock seconds remaining until this job reaches a terminal state, or `null` if not yet computable. Same quantity and same bound as `estimated_seconds`, measured later in the job's life — so it shares `EstimatedProcessingSeconds` rather than carrying its own copy of the audio-duration ceiling.",
          "anyOf": [
            {
              "$ref": "#/$defs/EstimatedProcessingSeconds"
            },
            {
              "enum": [
                null
              ]
            }
          ]
        }
      }
    },
    "JobShowTitle": {
      "description": "The show's title as it was when this job or read was created (ADR-0036), or `null` when it was created without one: before 0.14.0, or from a feed that names no show. For an upload it is `Uploads`. Copied once, never updated.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1,
          "maxLength": 300
        },
        {
          "type": "null"
        }
      ]
    },
    "JobState": {
      "type": "string",
      "enum": [
        "validating",
        "queued",
        "downloading",
        "transcribing",
        "merging",
        "completed",
        "failed",
        "cancelled"
      ],
      "description": "Legal transitions: validating → queued|failed|cancelled; queued → downloading|failed|cancelled; downloading → transcribing|failed; transcribing → merging|failed; merging → completed|failed. Terminal states (completed, failed, cancelled) have no further transitions. Cancellation is legal only from validating/queued; every non-terminal state may fail."
    },
    "Language": {
      "type": "string",
      "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{1,8})*$",
      "maxLength": 35,
      "description": "A BCP-47 language tag (general syntax check, not full IANA subtag validation)."
    },
    "RequestId": {
      "type": "string",
      "pattern": "^req_[A-Za-z0-9-]+$",
      "maxLength": 100
    },
    "ShowId": {
      "type": "string",
      "pattern": "^sh_[a-z2-7]{16}$",
      "description": "Canonical show identifier."
    },
    "TimingPrecision": {
      "type": "string",
      "enum": [
        "word",
        "segment",
        "none"
      ],
      "description": "How precisely segments/words are timed. ASR output targets `word`. Publisher-sourced transcripts report the precision the source actually provides and never claim word timing they do not have: plain text is `none`, segment-timed sources are `segment`, and only genuine word-timed sources are `word`."
    },
    "TranscriptArtifact": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "format"
      ],
      "description": "The JSON delivery of a completed job's transcript, embedded in `JobStatus` when `status` is `completed` and JSON delivery was requested. `format` is always `json` here: the other formats are delivered as raw bodies (`RawTranscriptArtifact`), never wrapped in this envelope. Payloads above the ~5 MB inline limit carry `transcript_url` (presigned, 24 h) plus `expires_at` instead of an inline `transcript`.",
      "properties": {
        "format": {
          "const": "json"
        },
        "transcript": {
          "$ref": "#/$defs/CanonicalTranscript"
        },
        "transcript_url": {
          "type": "string",
          "format": "uri",
          "maxLength": 2048
        },
        "expires_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "oneOf": [
        {
          "required": [
            "transcript"
          ]
        },
        {
          "required": [
            "transcript_url",
            "expires_at"
          ]
        }
      ]
    },
    "TranscriptSegment": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "start",
        "end",
        "speaker",
        "text"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1000000
        },
        "start": {
          "type": "number",
          "minimum": 0,
          "maximum": 129600,
          "description": "Start time in seconds."
        },
        "end": {
          "type": "number",
          "minimum": 0,
          "maximum": 129600,
          "description": "End time in seconds."
        },
        "speaker": {
          "enum": [
            null
          ],
          "description": "Always `null` in the MVP — diarization is post-MVP. A future diarized-speaker field is a deliberate, reviewed type change, not a silent widening."
        },
        "text": {
          "type": "string",
          "maxLength": 20000
        },
        "words": {
          "type": "array",
          "maxItems": 20000,
          "items": {
            "$ref": "#/$defs/TranscriptWord"
          },
          "description": "Present when `timing_precision` is `word`; absent otherwise."
        }
      }
    },
    "TranscriptSource": {
      "type": "string",
      "enum": [
        "qwen3-asr",
        "whisper-large-v3-turbo",
        "whisper-large-v3",
        "publisher"
      ],
      "description": "The ASR engine that produced this transcript, or `publisher` for passthrough."
    },
    "TranscriptWarning": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "segment",
        "type",
        "detail"
      ],
      "description": "A quality warning from the pipeline's own checks, attached to the segment it concerns. Presented as a heuristic, not an accuracy guarantee; the transcript is delivered and charged as usual. `type` is an open string rather than a closed enum; the documentation's output-formats page lists the values in use.",
      "properties": {
        "segment": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1000000
        },
        "type": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60
        },
        "detail": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        }
      }
    },
    "TranscriptWord": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "w",
        "s",
        "e"
      ],
      "properties": {
        "w": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "The word text."
        },
        "s": {
          "type": "number",
          "minimum": 0,
          "maximum": 129600,
          "description": "Start time in seconds."
        },
        "e": {
          "type": "number",
          "minimum": 0,
          "maximum": 129600,
          "description": "End time in seconds."
        }
      }
    }
  }
}

Work with this as data

Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for schemas

4 MCP tools reach this
  • find_json_schemasBrowse and filter every JSON Schema in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/audivo-dev-job-status"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.