Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Scribiz Uploads API
version: 1.0.0
description: 'Operations tagged Uploads across 2 of this provider''s published API definitions: openapi.json, scribiz-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
url: https://scribiz.com/api
tags:
- name: Uploads
paths:
/v1/transcribe:
post:
description: 'Multipart convenience: send the file as the `file` part (at most 100 MB) with optional `mode`, `language`, `options` (JSON) and `turnstile_token`. Returns the same 202 as POST /v1/context, plus `upload_id`. For larger or streamed files use PUT /v1/uploads.'
operationId: transcribe
requestBody:
content:
multipart/form-data:
schema:
properties:
file:
contentMediaType: application/octet-stream
type: string
language:
type: string
mode:
enum:
- auto
- captions
- audio
- visual
- full
- listen
- watch
- both
options:
description: JSON object as in ContextOptions.
type: string
turnstile_token:
type: string
required:
- file
type: object
required: true
responses:
'202':
content:
application/json:
schema:
$ref: '#/components/schemas/JobCreated'
description: Queued.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'402':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: quota_exceeded
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'411':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: length_required
'413':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: body_too_large, video_too_long
'415':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unsupported_media
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- all
- bearer:
- all
- cookie: []
- {}
summary: Upload a file and start a job
tags:
- Uploads
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
url: https://scribiz.com/api
/v1/uploads:
put:
description: Streams a single-chunk body to the server. Content-Length is required, 100 MB at most; the file lives 24 hours since last activity (pinned while a job references it) and ffprobe must recognise a media container. For larger or resumable uploads use POST /v1/uploads/sessions. Then POST /v1/context {"upload_id"}.
operationId: upload
parameters:
- in: header
name: X-File-Name
required: false
schema:
type: string
- in: header
name: Content-Length
required: true
schema:
type: integer
requestBody:
content:
application/octet-stream:
schema:
format: binary
type: string
required: true
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/Upload'
description: Received.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'408':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_too_slow
'411':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: length_required
'413':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: body_too_large
'415':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unsupported_media
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- all
- bearer:
- all
- cookie: []
- {}
summary: Upload a media file in one request
tags:
- Uploads
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
url: https://scribiz.com/api
/v1/uploads/{id}:
delete:
description: Deletes an unclaimed upload session and removes its `.part` file and upload folder from disk. Returns 409 `upload_in_use` if a job already claims the upload.
operationId: deleteUpload
parameters:
- description: The upload id (upl_...).
in: path
name: id
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
properties:
deleted:
const: true
status:
const: deleted
upload_id:
type: string
required:
- upload_id
- deleted
- status
type: object
description: Deleted.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'409':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_in_use
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- all
- bearer:
- all
- cookie: []
- {}
summary: Delete an unclaimed upload
tags:
- Uploads
get:
description: Returns the upload state (`receiving`, `probing`, `ready`, or `failed` with `reason`), current byte `offset`, and media metadata once probed.
operationId: getUpload
parameters:
- description: The upload id (upl_...).
in: path
name: id
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Upload'
description: The upload.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'410':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_expired
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- read
- bearer:
- read
- cookie: []
- {}
summary: Inspect an upload
tags:
- Uploads
head:
description: Returns `Upload-Offset`, `Upload-Length`, and `Upload-Status` headers for resuming an interrupted upload.
operationId: headUpload
parameters:
- description: The upload id (upl_...).
in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Current offset and status.
headers:
Upload-Length:
schema:
type: integer
Upload-Offset:
schema:
type: integer
Upload-Status:
schema:
enum:
- receiving
- probing
- ready
- failed
type: string
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'410':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_expired
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- read
- bearer:
- read
- cookie: []
- {}
summary: Read current upload offset
tags:
- Uploads
patch:
description: Append a chunk (at most 16 MiB) at `Upload-Offset`. On an offset mismatch answers 409 with the current `Upload-Offset` header and `offset` field. Idempotent per offset.
operationId: patchUpload
parameters:
- description: The upload id (upl_...).
in: path
name: id
required: true
schema:
type: string
- in: header
name: Upload-Offset
required: true
schema:
minimum: 0
type: integer
- in: header
name: Content-Length
required: false
schema:
maximum: 16777216
minimum: 0
type: integer
requestBody:
content:
application/octet-stream:
schema:
format: binary
type: string
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/UploadChunkAck'
description: Chunk appended.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'408':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_too_slow
'409':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: offset_mismatch
'410':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_expired
'413':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: body_too_large
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- all
- bearer:
- all
- cookie: []
- {}
summary: Append an upload chunk
tags:
- Uploads
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
url: https://scribiz.com/api
/v1/uploads/{id}/complete:
post:
description: Verifies the received length and SHA-256 checksum, returns 202, and runs `sniffMedia` and `measureDecodedSeconds` in the background. Poll GET /v1/uploads/{id} until `status` is `ready` or `failed`.
operationId: completeUpload
parameters:
- description: The upload id (upl_...).
in: path
name: id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
additionalProperties: false
properties:
sha256:
pattern: ^[0-9A-Fa-f]{64}$
type: string
type: object
required: false
responses:
'202':
content:
application/json:
schema:
$ref: '#/components/schemas/Upload'
description: Probing started.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'409':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_incomplete
'410':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: upload_expired
'415':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unsupported_media
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
security:
- apiKey:
- all
- bearer:
- all
- cookie: []
- {}
summary: Complete a resumable upload and start probing
tags:
- Uploads
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
url: https://scribiz.com/api
/v1/uploads/sessions:
post:
description: Start a tus-style resumable upload session (up to 1024 MB). Reserves the declared bytes and returns the `upload_id` and `chunk_bytes` (8 MiB). Append chunks with PATCH /v1/uploads/{id}, then call POST /v1/uploads/{id}/complete and poll GET /v1/uploads/{id} until `status` is `ready`.
operationId: createUploadSession
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UploadSessionRequest'
description: JSON
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/UploadSessionCreated'
description: Session created.
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: invalid_request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unauthorized, invalid_api_key or invalid_token
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: insufficient_scope, session_required, account_required, turnstile_required, bad_origin
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: not_found
'413':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: body_too_large
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: rate_limited, too_many_in_flight, anonymous_limit, daily_spend_limit
'503':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: busy
security:
- apiKey:
- all
- bearer:
- all
- cookie: []
- {}
summary: Start a resumable upload session
tags:
- Uploads
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
url: https://scribiz.com/api
components:
schemas:
Upload:
properties:
bytes:
type: integer
duration_seconds:
type:
- number
- 'null'
expires_at:
type: integer
file_name:
type:
- string
- 'null'
has_audio:
type: boolean
has_video:
type: boolean
mime:
type:
- string
- 'null'
offset:
type: integer
reason:
type:
- string
- 'null'
sha256:
type:
- string
- 'null'
status:
enum:
- receiving
- probing
- ready
- failed
upload_id:
type: string
required:
- upload_id
- status
- offset
- bytes
- has_audio
- has_video
- expires_at
type: object
Error:
properties:
error:
additionalProperties: true
properties:
code:
description: snake_case.
type: string
engineCode:
description: The engine's own code (QUOTA, SOURCE_UNAVAILABLE, ...) when there is one.
type: string
hint:
type: string
message:
type: string
required:
- code
- message
type: object
required:
- error
type: object
JobCreated:
properties:
degraded:
type: object
estimate:
$ref: '#/components/schemas/Quote'
events_url:
type: string
idempotent_replay:
type: boolean
job_id:
type: string
mode:
type: string
queue_position:
type: integer
result_url:
type: string
status:
type: string
upload_id:
type: string
required:
- job_id
- status
- events_url
- result_url
- estimate
type: object
UploadSessionCreated:
properties:
chunk_bytes:
type: integer
expires_at:
type: integer
offset:
type: integer
upload_id:
type: string
required:
- upload_id
- chunk_bytes
- offset
- expires_at
type: object
UploadSessionRequest:
additionalProperties: false
properties:
bytes:
maximum: 1073741824
minimum: 1
type: integer
file_name:
maxLength: 100
type: string
mime:
maxLength: 200
type: string
name:
maxLength: 100
type: string
sha256:
pattern: ^[0-9A-Fa-f]{64}$
type: string
required:
- bytes
type: object
Quote:
properties:
cached:
description: 'Everything is already stored: nothing is charged.'
type: boolean
caption_credits:
description: Maximum caption credits for a strict YouTube request. Media minutes are zero.
minimum: 0
type: integer
charges_as:
enum:
- caption-item
- captions
- audio
- visual
- full
length_known:
const: false
description: Present (false) when the length of the source could not be read before the run (a YouTube link that yt-dlp and the YouTube page both refused; a direct media link not yet downloaded). The job is charged from the length it measures.
max_media_seconds:
description: 'Only with `length_known: false` on a YouTube link: the longest stretch the job reads (a clip that ends there): never more than the plan allows per video and never more than the minutes left. `minutes` is the most the job can then use. When the server can get the video''s own captions they answer instead, also for a longer video, and the job costs less.'
type: number
media_seconds:
description: 'Seconds of media the quote is for; null when the length is not known (`length_known: false`).'
type:
- number
- 'null'
minutes:
description: 'Minutes this job uses when it runs as quoted (0 when cached), including the half minute for each media minute when the full proofread is part of it (`proofread: "full"` or a `vocabulary`). It is charged only if the pass runs. With `length_known: false`: the most it can use.'
type: number
tiers:
items:
enum:
- captions
- audio
- visual
- synthesis
type: array
required:
- minutes
- media_seconds
- tiers
- cached
- charges_as
type: object
UploadChunkAck:
properties:
bytes:
type: integer
expires_at:
type: integer
offset:
type: integer
upload_id:
type: string
required:
- upload_id
- offset
- bytes
- expires_at
type: object
securitySchemes:
apiKey:
description: 'An API key (sbz_live_...), as X-API-Key. Keys are made in the dashboard or by `scribiz login`. Each key has one scope, named in an operation''s security requirement. `all`: Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read. `mcp`: The remote MCP server at /mcp. Includes read. `read`: Read jobs and their events.'
in: header
name: X-API-Key
type: apiKey
x-scopes:
all: 'Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read.'
mcp: The remote MCP server at /mcp. Includes read.
read: Read jobs and their events.
bearer:
description: 'An API key (sbz_live_...) or a session token from the device flow. Each key has one scope, named in an operation''s security requirement. `all`: Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read. `mcp`: The remote MCP server at /mcp. Includes read. `read`: Read jobs and their events. A session token has every scope.'
scheme: bearer
type: http
x-scopes:
all: 'Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read.'
mcp: The remote MCP server at /mcp. Includes read.
read: Read jobs and their events.
cookie:
description: The browser session (same-origin /api/*).
in: cookie
name: better-auth.session_token
type: apiKey
x-refined-from:
- openapi.json
- scribiz-openapi.json