{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Video to Notes API",
    "version": "1.0.0",
    "summary": "Transcripts and AI notes for uploaded audio and video files.",
    "description": "Included in active Basic and Plus plans. Keys are server-side secrets. Guide: https://video-to-notes.com/developers/ Reference: https://video-to-notes.com/developers/api-reference.html"
  },
  "externalDocs": {
    "url": "https://video-to-notes.com/developers/api-reference.html"
  },
  "servers": [
    {
      "url": "https://api.video-to-notes.com"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "account",
      "description": "Account"
    },
    {
      "name": "uploads",
      "description": "Files are uploaded in parts straight to storage through signed URLs. An account can have one active upload at a time."
    },
    {
      "name": "jobs",
      "description": "A job processes one uploaded file into a transcript and notes. An account can run one job at a time."
    },
    {
      "name": "results",
      "description": "Results"
    }
  ],
  "paths": {
    "/api/v1/account": {
      "get": {
        "operationId": "getAccount",
        "tags": [
          "account"
        ],
        "summary": "Get the account, plan and limits",
        "description": "Returns the plan, the remaining plan seconds, the end of the current allowance and the capabilities and limits that apply to the account right now. Read it before you upload: when eligible or capabilities.api_admission_enabled is false, new jobs are refused.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/account"
                },
                "example": {
                  "plan": "basic",
                  "eligible": true,
                  "remaining_seconds": 64800,
                  "allowance_expires_at": 1792886400,
                  "capabilities": {
                    "api_admission_enabled": true,
                    "key_creation_enabled": true,
                    "server_upload_enabled": true,
                    "long_jobs": true,
                    "formats": [
                      "mp4",
                      "m4v",
                      "mov",
                      "webm",
                      "mkv",
                      "ogv",
                      "avi",
                      "wmv",
                      "asf",
                      "flv",
                      "mpg",
                      "mpeg",
                      "vob",
                      "ts",
                      "mts",
                      "m2ts",
                      "3gp",
                      "3g2",
                      "mxf",
                      "mp3",
                      "m4a",
                      "aac",
                      "wav",
                      "flac",
                      "ogg",
                      "oga",
                      "opus",
                      "wma",
                      "amr",
                      "aiff",
                      "aif",
                      "caf",
                      "ac3"
                    ],
                    "audio_languages": [
                      "auto",
                      "af",
                      "am",
                      "ar",
                      "hy",
                      "az",
                      "be",
                      "bn",
                      "bs",
                      "bg",
                      "my",
                      "ca",
                      "zh",
                      "hr",
                      "cs",
                      "da",
                      "nl",
                      "en",
                      "et",
                      "tl",
                      "fi",
                      "fr",
                      "gl",
                      "ka",
                      "de",
                      "el",
                      "gu",
                      "ha",
                      "he",
                      "hi",
                      "hu",
                      "is",
                      "id",
                      "it",
                      "ja",
                      "kn",
                      "kk",
                      "km",
                      "ko",
                      "lv",
                      "lt",
                      "mk",
                      "ms",
                      "ml",
                      "mt",
                      "mr",
                      "mn",
                      "ne",
                      "no",
                      "fa",
                      "pl",
                      "pt",
                      "pa",
                      "ro",
                      "ru",
                      "sr",
                      "sk",
                      "sl",
                      "es",
                      "sw",
                      "sv",
                      "ta",
                      "te",
                      "th",
                      "tr",
                      "uk",
                      "uz",
                      "vi"
                    ],
                    "notes_languages": [
                      "auto",
                      "af",
                      "am",
                      "ar",
                      "hy",
                      "az",
                      "be",
                      "bn",
                      "bs",
                      "bg",
                      "my",
                      "ca",
                      "zh",
                      "hr",
                      "cs",
                      "da",
                      "nl",
                      "en",
                      "et",
                      "tl",
                      "fi",
                      "fr",
                      "gl",
                      "ka",
                      "de",
                      "el",
                      "gu",
                      "ha",
                      "he",
                      "hi",
                      "hu",
                      "is",
                      "id",
                      "it",
                      "ja",
                      "kn",
                      "kk",
                      "km",
                      "ko",
                      "lv",
                      "lt",
                      "mk",
                      "ms",
                      "ml",
                      "mt",
                      "mr",
                      "mn",
                      "ne",
                      "no",
                      "fa",
                      "pl",
                      "pt",
                      "pa",
                      "ro",
                      "ru",
                      "sr",
                      "sk",
                      "sl",
                      "es",
                      "sw",
                      "sv",
                      "ta",
                      "te",
                      "th",
                      "tr",
                      "uk",
                      "uz",
                      "vi"
                    ],
                    "download_formats": [
                      "transcript_txt",
                      "notes_md",
                      "notes_html",
                      "notes_pdf"
                    ],
                    "email_opt_in": false,
                    "limits": {
                      "max_upload_bytes": 8589934592,
                      "max_selection_seconds": null,
                      "active_jobs": 1,
                      "active_uploads": 1,
                      "daily_uploads": 10,
                      "daily_upload_bytes": 21474836480,
                      "new_requests_per_minute": 12,
                      "read_requests_per_minute": 60,
                      "poll_after_seconds": 5,
                      "result_page_bytes": 1000000,
                      "result_page_items": 32,
                      "upload_url_seconds": 900,
                      "download_url_seconds": 600,
                      "result_retention_seconds": 86400,
                      "recovery_retention_seconds": 172800,
                      "idempotency_retention_seconds": 34560000
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/uploads": {
      "post": {
        "operationId": "createUpload",
        "tags": [
          "uploads"
        ],
        "summary": "Create an upload",
        "description": "Starts an upload. Send the exact file size in bytes and the file extension. The response gives part_size and part_count: split the file into parts of part_size bytes; the last part may be smaller.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/uploadCreate"
              },
              "example": {
                "byte_size": 1048576,
                "extension": "mp4"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/upload"
                },
                "example": {
                  "upload_id": "upload-1",
                  "state": "created",
                  "expires_at": 1792807200,
                  "part_size": 16777216,
                  "part_count": 1,
                  "error": null
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/uploads/{upload_id}/parts": {
      "post": {
        "operationId": "requestPartUrls",
        "tags": [
          "uploads"
        ],
        "summary": "Get signed part upload URLs",
        "description": "Returns signed upload URLs for 1 to 100 part numbers. Each URL is valid for up to 15 minutes; request a new one when it expires or when a part has to be sent again.",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "upload-1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/uploadParts"
              },
              "example": {
                "part_numbers": [
                  1
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/uploadTargets"
                },
                "example": {
                  "upload_id": "upload-1",
                  "targets": [
                    {
                      "part_number": 1,
                      "url": "https://example.invalid/signed",
                      "expires_at": 1792800900
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/uploads/{upload_id}/complete": {
      "post": {
        "operationId": "completeUpload",
        "tags": [
          "uploads"
        ],
        "summary": "Complete an upload",
        "description": "Finishes the upload. Send every part number with its ETag. Completing an upload does not start processing; create a job next.",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "upload-1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/uploadComplete"
              },
              "example": {
                "parts": [
                  {
                    "part_number": 1,
                    "etag": "opaque-etag"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/upload"
                },
                "example": {
                  "upload_id": "upload-1",
                  "state": "uploaded",
                  "expires_at": 1792807200,
                  "part_size": 16777216,
                  "part_count": 1,
                  "error": null
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/uploads/{upload_id}": {
      "get": {
        "operationId": "getUpload",
        "tags": [
          "uploads"
        ],
        "summary": "Get an upload",
        "description": "Returns the state of an upload: created, uploading, uploaded, probing, probed, failed, aborted or expired.",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "upload-1"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/upload"
                },
                "example": {
                  "upload_id": "upload-1",
                  "state": "uploaded",
                  "expires_at": 1792807200,
                  "part_size": 16777216,
                  "part_count": 1,
                  "error": null
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/uploads/{upload_id}/abort": {
      "post": {
        "operationId": "abortUpload",
        "tags": [
          "uploads"
        ],
        "summary": "Abort an upload",
        "description": "Cancels an upload you will not use and frees the upload slot of the account. Calling it again is safe.",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "upload-1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/empty"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/upload"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/jobs": {
      "post": {
        "operationId": "createJob",
        "tags": [
          "jobs"
        ],
        "summary": "Create a job",
        "description": "Starts processing an uploaded file. The Idempotency-Key header is required: 1 to 128 printable ASCII characters without spaces, new for every job. Optional fields are range (start_seconds and end_seconds, both required when present), audio_language and notes_language. Returns 202 with the job in state preparing. The same key with the same body returns the same job; the same key with another body returns 409.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A new random value per intended job; repeat it to recover the same job.",
            "schema": {
              "type": "string",
              "pattern": "^[!-~]{1,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/jobCreate"
              },
              "example": {
                "upload_id": "upload-1",
                "range": {
                  "start_seconds": 5,
                  "end_seconds": 60
                },
                "audio_language": null,
                "notes_language": "en"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/job"
                },
                "example": {
                  "job_id": "job-1",
                  "state": "preparing",
                  "stage": "probe",
                  "created_at": 1792800000,
                  "expires_at": 1792807200,
                  "result_expires_at": null,
                  "idempotency_expires_at": 1827360000,
                  "poll_after_seconds": 5,
                  "status_url": "/api/v1/jobs/job-1",
                  "result_url": "/api/v1/jobs/job-1/result",
                  "completed_units": 0,
                  "total_units": null,
                  "charged_seconds": 0,
                  "result_available": false,
                  "can_resume": false,
                  "warnings": [],
                  "error": null
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/jobs/{job_id}": {
      "get": {
        "operationId": "getJob",
        "tags": [
          "jobs"
        ],
        "summary": "Get a job",
        "description": "Returns the state, the current stage, the progress (completed_units of total_units), charged_seconds, warnings and any error. A failed job still returns 200; read its error.",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "job-1"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/job"
                },
                "example": {
                  "job_id": "job-1",
                  "state": "completed",
                  "stage": "terminal",
                  "created_at": 1792800000,
                  "expires_at": 1792807200,
                  "result_expires_at": 1792886400,
                  "idempotency_expires_at": 1827360000,
                  "poll_after_seconds": 5,
                  "status_url": "/api/v1/jobs/job-1",
                  "result_url": "/api/v1/jobs/job-1/result",
                  "completed_units": 8,
                  "total_units": 8,
                  "charged_seconds": 1140,
                  "result_available": true,
                  "can_resume": false,
                  "warnings": [],
                  "error": null
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/jobs/{job_id}/cancel": {
      "post": {
        "operationId": "cancelJob",
        "tags": [
          "jobs"
        ],
        "summary": "Cancel a job",
        "description": "Stops a job. Finished parts stay available and reserved time that was not used is returned. Calling it again is safe.",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "job-1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/empty"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/job"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/jobs/{job_id}/resume": {
      "post": {
        "operationId": "resumeJob",
        "tags": [
          "jobs"
        ],
        "summary": "Resume a job",
        "description": "Continues an interrupted job when its status reports can_resume: true. It needs an active plan and checks your remaining time again. Parts that were already processed are not charged again.",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "job-1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/empty"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/job"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/jobs/{job_id}/result": {
      "get": {
        "operationId": "getResult",
        "tags": [
          "results"
        ],
        "summary": "Get a result page",
        "description": "Returns one page of results with up to 32 items and 1 MB. Items are ordered and have a kind: transcript (text with timed segments), notes (Markdown), gap (audio that could not be processed) or warning. Pass next_cursor as the cursor query parameter to get the next page, until it is null. Each page can list up to four download links in artifacts, valid for up to 10 minutes. If the job is resumed while you read, the API returns 409 JOB_CONFLICT; start again from the first page.",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "example": "job-1"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The next_cursor of the previous page; omit it for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 2048
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/result"
                },
                "example": {
                  "job_id": "job-1",
                  "snapshot": "generation-1",
                  "items": [
                    {
                      "index": 0,
                      "kind": "transcript",
                      "text": "Welcome to the weekly planning meeting.",
                      "segments": [
                        {
                          "text": "Welcome to the weekly planning meeting.",
                          "start_seconds": 0,
                          "end_seconds": 4.2,
                          "timing_quality": "approximate",
                          "timing_method": "provider_segment"
                        }
                      ]
                    },
                    {
                      "index": 0,
                      "kind": "notes",
                      "text": "## Summary\n\nThe team agreed on the launch plan.\n\n## Key points\n\n- Launch moves to Monday."
                    }
                  ],
                  "next_cursor": "opaque-account-bound-cursor",
                  "artifacts": [
                    {
                      "format": "notes_md",
                      "url": "https://example.invalid/signed-notes",
                      "expires_at": 1792800600
                    }
                  ],
                  "charged_seconds": 1140,
                  "partial": false,
                  "expires_at": 1792886400
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key (vtn_prod_...) created while signed in on the website."
      }
    },
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/error"
            },
            "example": {
              "error": {
                "code": "UNAUTHORIZED",
                "message": "Request refused.",
                "retryable": false,
                "retry_after_seconds": null
              },
              "request_id": "request-1"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests; wait for Retry-After.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/error"
            },
            "example": {
              "error": {
                "code": "RATE_LIMITED",
                "message": "Request refused.",
                "retryable": true,
                "retry_after_seconds": 5
              },
              "request_id": "request-1"
            }
          }
        }
      }
    },
    "schemas": {
      "empty": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      },
      "keyCreate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "name"
        ]
      },
      "keyMetadata": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "key_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "masked_key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "created_at": {
            "type": "integer",
            "minimum": 0
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "revoked_at": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "key_id",
          "name",
          "masked_key",
          "created_at",
          "expires_at",
          "last_used_at",
          "revoked_at"
        ]
      },
      "keyCreated": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "key": {
            "$ref": "#/components/schemas/keyMetadata"
          },
          "secret": {
            "type": "string",
            "pattern": "^vtn_(dev|prod)_[A-Za-z0-9_-]{43,}$"
          }
        },
        "required": [
          "key",
          "secret"
        ]
      },
      "keyList": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/keyMetadata"
            },
            "maxItems": 100
          }
        },
        "required": [
          "keys"
        ]
      },
      "limits": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "max_upload_bytes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 8589934592
          },
          "max_selection_seconds": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "active_jobs": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1
          },
          "active_uploads": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1
          },
          "daily_uploads": {
            "type": "integer",
            "minimum": 0
          },
          "daily_upload_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "new_requests_per_minute": {
            "type": "integer",
            "minimum": 0
          },
          "read_requests_per_minute": {
            "type": "integer",
            "minimum": 0
          },
          "poll_after_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "result_page_bytes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000000
          },
          "result_page_items": {
            "type": "integer",
            "minimum": 0,
            "maximum": 32
          },
          "upload_url_seconds": {
            "type": "integer",
            "minimum": 0,
            "maximum": 900
          },
          "download_url_seconds": {
            "type": "integer",
            "minimum": 0,
            "maximum": 600
          },
          "result_retention_seconds": {
            "type": "integer",
            "minimum": 0,
            "maximum": 86400
          },
          "recovery_retention_seconds": {
            "type": "integer",
            "minimum": 0,
            "maximum": 172800
          },
          "idempotency_retention_seconds": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "max_upload_bytes",
          "max_selection_seconds",
          "active_jobs",
          "active_uploads",
          "daily_uploads",
          "daily_upload_bytes",
          "new_requests_per_minute",
          "read_requests_per_minute",
          "poll_after_seconds",
          "result_page_bytes",
          "result_page_items",
          "upload_url_seconds",
          "download_url_seconds",
          "result_retention_seconds",
          "recovery_retention_seconds",
          "idempotency_retention_seconds"
        ]
      },
      "capabilities": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "api_admission_enabled": {
            "type": "boolean"
          },
          "key_creation_enabled": {
            "type": "boolean"
          },
          "server_upload_enabled": {
            "type": "boolean"
          },
          "long_jobs": {
            "type": "boolean"
          },
          "formats": {
            "type": "array",
            "items": {
              "enum": [
                "mp4",
                "m4v",
                "mov",
                "webm",
                "mkv",
                "ogv",
                "avi",
                "wmv",
                "asf",
                "flv",
                "mpg",
                "mpeg",
                "vob",
                "ts",
                "mts",
                "m2ts",
                "3gp",
                "3g2",
                "mxf",
                "mp3",
                "m4a",
                "aac",
                "wav",
                "flac",
                "ogg",
                "oga",
                "opus",
                "wma",
                "amr",
                "aiff",
                "aif",
                "caf",
                "ac3"
              ]
            },
            "maxItems": 33
          },
          "audio_languages": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 35
            },
            "maxItems": 200
          },
          "notes_languages": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 35
            },
            "maxItems": 200
          },
          "download_formats": {
            "type": "array",
            "items": {
              "enum": [
                "transcript_txt",
                "notes_md",
                "notes_html",
                "notes_pdf"
              ]
            },
            "maxItems": 4
          },
          "email_opt_in": {
            "const": false
          },
          "limits": {
            "$ref": "#/components/schemas/limits"
          },
          "result_billing": {
            "type": "boolean"
          }
        },
        "required": [
          "api_admission_enabled",
          "key_creation_enabled",
          "server_upload_enabled",
          "long_jobs",
          "formats",
          "audio_languages",
          "notes_languages",
          "download_formats",
          "email_opt_in",
          "limits"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "long_jobs": {
                  "const": false
                }
              },
              "required": [
                "long_jobs"
              ]
            },
            "then": {
              "properties": {
                "limits": {
                  "properties": {
                    "max_selection_seconds": {
                      "type": "number",
                      "exclusiveMinimum": 0,
                      "maximum": 7200
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "account": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "plan": {
            "enum": [
              "basic",
              "plus",
              null
            ]
          },
          "eligible": {
            "type": "boolean"
          },
          "remaining_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "allowance_expires_at": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "capabilities": {
            "$ref": "#/components/schemas/capabilities"
          },
          "limit_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "used_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "reserved_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "available_seconds": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "plan",
          "eligible",
          "remaining_seconds",
          "allowance_expires_at",
          "capabilities"
        ]
      },
      "uploadCreate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 8589934592
          },
          "extension": {
            "enum": [
              "mp4",
              "m4v",
              "mov",
              "webm",
              "mkv",
              "ogv",
              "avi",
              "wmv",
              "asf",
              "flv",
              "mpg",
              "mpeg",
              "vob",
              "ts",
              "mts",
              "m2ts",
              "3gp",
              "3g2",
              "mxf",
              "mp3",
              "m4a",
              "aac",
              "wav",
              "flac",
              "ogg",
              "oga",
              "opus",
              "wma",
              "amr",
              "aiff",
              "aif",
              "caf",
              "ac3"
            ],
            "type": "string"
          }
        },
        "required": [
          "byte_size",
          "extension"
        ]
      },
      "uploadParts": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "part_numbers": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true
          }
        },
        "required": [
          "part_numbers"
        ]
      },
      "completedPart": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "part_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "etag": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        },
        "required": [
          "part_number",
          "etag"
        ]
      },
      "uploadComplete": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "parts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/completedPart"
            },
            "minItems": 1,
            "maxItems": 1000
          }
        },
        "required": [
          "parts"
        ]
      },
      "uploadTarget": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "part_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "url": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 8192
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "part_number",
          "url",
          "expires_at"
        ]
      },
      "uploadTargets": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "upload_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "targets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/uploadTarget"
            },
            "maxItems": 100
          }
        },
        "required": [
          "upload_id",
          "targets"
        ]
      },
      "upload": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "upload_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "state": {
            "enum": [
              "created",
              "uploading",
              "uploaded",
              "probing",
              "probed",
              "failed",
              "aborted",
              "expired"
            ]
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          },
          "part_size": {
            "type": "integer",
            "minimum": 0
          },
          "part_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/errorDetail"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "upload_id",
          "state",
          "expires_at",
          "part_size",
          "part_count",
          "error"
        ]
      },
      "range": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "start_seconds": {
            "type": "number",
            "minimum": 0
          },
          "end_seconds": {
            "type": "number",
            "minimum": 0
          }
        },
        "required": [
          "start_seconds",
          "end_seconds"
        ]
      },
      "jobCreate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "upload_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "range": {
            "$ref": "#/components/schemas/range"
          },
          "audio_language": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 35
              },
              {
                "type": "null"
              }
            ]
          },
          "notes_language": {
            "type": "string",
            "minLength": 1,
            "maxLength": 35
          }
        },
        "required": [
          "upload_id"
        ]
      },
      "resultQuery": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "cursor": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048
          }
        },
        "required": []
      },
      "errorDetail": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "enum": [
              "UNAUTHORIZED",
              "FORBIDDEN",
              "NOT_FOUND",
              "VALIDATION_ERROR",
              "PLAN_REQUIRED",
              "INSUFFICIENT_BALANCE",
              "CAPABILITY_DISABLED",
              "UNSUPPORTED_MEDIA",
              "MEDIA_TOO_LARGE",
              "PROBE_FAILED",
              "IDEMPOTENCY_CONFLICT",
              "IDEMPOTENCY_EXPIRED",
              "JOB_CONFLICT",
              "RESULT_EXPIRED",
              "RATE_LIMITED",
              "UNAVAILABLE"
            ]
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024
          },
          "retryable": {
            "type": "boolean"
          },
          "retry_after_seconds": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "context": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "limit_seconds": {
                "type": "integer",
                "minimum": 0
              },
              "used_seconds": {
                "type": "integer",
                "minimum": 0
              },
              "reserved_seconds": {
                "type": "integer",
                "minimum": 0
              },
              "available_seconds": {
                "type": "integer",
                "minimum": 0
              },
              "requested_seconds": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "required": [
          "code",
          "message",
          "retryable",
          "retry_after_seconds"
        ]
      },
      "error": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "error": {
            "$ref": "#/components/schemas/errorDetail"
          },
          "request_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        "required": [
          "error",
          "request_id"
        ]
      },
      "job": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "job_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "state": {
            "enum": [
              "preparing",
              "queued",
              "processing",
              "completed",
              "completed_with_gaps",
              "interrupted",
              "cancelled",
              "failed",
              "expired"
            ]
          },
          "stage": {
            "enum": [
              "probe",
              "planning",
              "admission",
              "extraction",
              "transcription",
              "notes",
              "publication",
              "terminal"
            ]
          },
          "created_at": {
            "type": "integer",
            "minimum": 0
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          },
          "result_expires_at": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "idempotency_expires_at": {
            "type": "integer",
            "minimum": 0
          },
          "poll_after_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "status_url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512
          },
          "result_url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512
          },
          "completed_units": {
            "type": "integer",
            "minimum": 0
          },
          "total_units": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "charged_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "result_available": {
            "type": "boolean"
          },
          "can_resume": {
            "type": "boolean"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 1024
            },
            "maxItems": 100
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/errorDetail"
              },
              {
                "type": "null"
              }
            ]
          },
          "settlement": {
            "description": "Authoritative billing state of one paid operation pinned to billing policy 66.1 (reserve upfront, charge once when the requested result is durably ready). Additive: only operations admitted under 66.1 carry it; recovery policy 50.1 stays independent. Clients never send it and never assert readiness.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "kind",
              "billing_policy",
              "recovery_policy",
              "requested",
              "attempt",
              "result",
              "hold",
              "charge",
              "next_action"
            ],
            "properties": {
              "kind": {
                "const": "paid-settlement-v1"
              },
              "billing_policy": {
                "const": "66.1"
              },
              "recovery_policy": {
                "const": "50.1"
              },
              "requested": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "product",
                  "formats"
                ],
                "description": "Pinned at admission; a client cannot change it mid-run.",
                "properties": {
                  "product": {
                    "enum": [
                      "transcript",
                      "notes"
                    ]
                  },
                  "formats": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 4,
                    "uniqueItems": true,
                    "items": {
                      "enum": [
                        "transcript_txt",
                        "notes_md",
                        "notes_html",
                        "notes_pdf"
                      ]
                    }
                  }
                }
              },
              "attempt": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "number",
                  "revision"
                ],
                "description": "The funded attempt. A retry, a notes-only retry or a resume opens a new number with a fresh hold; it never resets provider budgets.",
                "properties": {
                  "number": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 7
                  },
                  "revision": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "deadline": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "description": "Immutable wall deadline of this attempt (epoch seconds)."
                  },
                  "progress_deadline": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "description": "When the hold is released without new meaningful progress (epoch seconds, server clock)."
                  }
                }
              },
              "result": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "state"
                ],
                "properties": {
                  "state": {
                    "enum": [
                      "processing",
                      "ready",
                      "failed",
                      "stopped"
                    ],
                    "description": "ready = the server committed readiness proof for the requested product and formats; transcription completing alone is never ready."
                  },
                  "reason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 64
                  },
                  "published_at": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0
                  },
                  "expires_at": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "description": "Result downloads end: first owner-accessible publication + 86400 s."
                  }
                }
              },
              "hold": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "state",
                  "seconds"
                ],
                "properties": {
                  "state": {
                    "enum": [
                      "held",
                      "release_pending",
                      "released",
                      "captured",
                      "none"
                    ],
                    "description": "release_pending: the attempt ended but the ledger has not confirmed the release yet (never shown as available time)."
                  },
                  "seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Seconds this attempt reserved before work."
                  }
                }
              },
              "charge": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "state",
                  "published_seconds"
                ],
                "properties": {
                  "state": {
                    "enum": [
                      "pending",
                      "final"
                    ]
                  },
                  "published_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Cumulative once-only charge for results already published to the owner."
                  },
                  "attempt_seconds": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Net change made by this attempt's settlement: 0 for a failed attempt, negative for a credit of earlier normal-rate coverage."
                  },
                  "discounted": {
                    "type": "boolean",
                    "description": "The sticky completed-gap half rate applies."
                  }
                }
              },
              "next_action": {
                "enum": [
                  "none",
                  "wait",
                  "resume",
                  "retry_notes",
                  "retry_delivery"
                ],
                "description": "resume = missing audio; retry_notes = notes/exports only, no audio replay; retry_delivery = email only, no inference."
              },
              "resume_available": {
                "type": "boolean"
              }
            }
          }
        },
        "required": [
          "job_id",
          "state",
          "stage",
          "created_at",
          "expires_at",
          "result_expires_at",
          "idempotency_expires_at",
          "poll_after_seconds",
          "status_url",
          "result_url",
          "completed_units",
          "total_units",
          "charged_seconds",
          "result_available",
          "can_resume",
          "warnings",
          "error"
        ]
      },
      "segment": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 100000
          },
          "start_seconds": {
            "type": "number",
            "minimum": 0
          },
          "end_seconds": {
            "type": "number",
            "minimum": 0
          },
          "timing_quality": {
            "enum": [
              "aligned",
              "approximate",
              "unavailable"
            ]
          },
          "timing_method": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          }
        },
        "required": [
          "text",
          "start_seconds",
          "end_seconds",
          "timing_quality",
          "timing_method"
        ]
      },
      "gap": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "start_seconds": {
            "type": "number",
            "minimum": 0
          },
          "end_seconds": {
            "type": "number",
            "minimum": 0
          },
          "reason": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        },
        "required": [
          "start_seconds",
          "end_seconds",
          "reason"
        ]
      },
      "resultItem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "kind": {
            "enum": [
              "transcript",
              "notes",
              "gap",
              "warning"
            ]
          },
          "text": {
            "type": "string",
            "maxLength": 500000
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/segment"
            },
            "maxItems": 1000
          },
          "gap": {
            "$ref": "#/components/schemas/gap"
          }
        },
        "required": [
          "index",
          "kind"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "transcript"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "text"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "notes"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "text"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "gap"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "gap"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "warning"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "text"
              ]
            }
          }
        ]
      },
      "artifact": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "format": {
            "enum": [
              "transcript_txt",
              "notes_md",
              "notes_html",
              "notes_pdf"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 8192
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "format",
          "url",
          "expires_at"
        ]
      },
      "result": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "job_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "snapshot": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/resultItem"
            },
            "maxItems": 32
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ]
          },
          "artifacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/artifact"
            },
            "maxItems": 4
          },
          "charged_seconds": {
            "type": "integer",
            "minimum": 0
          },
          "partial": {
            "type": "boolean"
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "job_id",
          "snapshot",
          "items",
          "next_cursor",
          "artifacts",
          "charged_seconds",
          "partial",
          "expires_at"
        ]
      }
    }
  }
}
