Audioscrape Items API

Universal audio items — podcast episodes, uploads, conference talks, anything with a transcript. The `source_type` field distinguishes formats.

Operations 4

POST /api/datasets/{id}/items Upload audio into a dataset #
GET /api/items List audio items #
GET /api/items/{item_id} Get audio item #
GET /api/items/{item_id}/transcript Get item transcript #

Work with this as data

Every API 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 apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • 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 API
curl "https://apis.io/api/v1/apis/audioscrape-com:audioscrape-com-items-api"
All apis
curl "https://apis.io/api/v1/apis?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.

OpenAPI Specification

audioscrape-com-items-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Audioscrape Com Items API
  version: '2026-05-16'
  contact:
    name: Audioscrape
    url: https://www.audioscrape.com
    email: lukas@audioscrape.com
  license:
    name: ''
  description: 'Operations tagged Items across 2 of this provider''s published API definitions: audioscrape-com-openapi.json, audioscrape-com-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://www.audioscrape.com
  description: Production
tags:
- name: Items
  description: Universal audio items — podcast episodes, uploads, conference talks, anything with a transcript. The `source_type` field distinguishes formats.
paths:
  /api/datasets/{id}/items:
    post:
      tags:
      - Items
      summary: Upload audio into a dataset
      description: 'Two intake modes:

        • `Content-Type: multipart/form-data` — form fields `audio` (file), optional `title`, `description`

        • `Content-Type: application/json` — `{ "audio_url": "https://...", "title": "...", "description": "..." }`


        JSON mode is the natural fit when the audio is already hosted (S3 presigned URL, CDN, your own server).

        Multipart is the natural fit for client-side files (browser uploads, scripts streaming local files).

        Both modes converge on the same storage + transcription pipeline; the resulting item is identical.

        Transcription minutes consumed count against your plan''s monthly quota (see `/api/me/usage`).

        After upload, fetch full metadata at `GET /api/items/{item_id}` once transcription completes.


        ## Constraints


        • **File size:** Free tier is hard-capped at **400 MB** per audio upload regardless of dataset config (**1 GB** for video and for containers intake re-wraps — amr, 3gp, wma, aiff, caf, mpeg — since only the extracted audio is kept). Paid plans honour the dataset''s `max_file_size_mb` (default 500 MB). Exceeding the cap returns `413 Payload Too Large`; JSON-mode `audio_url` is fetched under the same cap. (The MCP connector''s `transcribe_audio` link path and the web paste-a-link import fetch in the pipeline without a byte cap.)

        • **URL-fetch safety (JSON mode):** `audio_url` must use `https://`. URLs that resolve to private, link-local, loopback, or otherwise internal IP ranges are rejected (SSRF guard) with `422 Unprocessable Entity`.

        • **Dataset configuration:** The target dataset must have `content_type = ''uploads''`. Datasets backed by RSS feeds or other source types return `409 Conflict`.'
      operationId: upload_item_external
      parameters:
      - name: id
        in: path
        description: Numeric dataset ID. Caller must be a member of the dataset's parent library.
        required: true
        schema:
          type: integer
          format: int64
      requestBody:
        description: '**This endpoint accepts TWO content types — pick one based on where the audio lives:**


          1. **`application/json`** (documented schema below) — body shape `{ "audio_url": "https://...", "title": "...", "description": "..." }`. Use this when the audio is already hosted at a public HTTPS URL.


          2. **`multipart/form-data`** (NOT shown in the schema above — utoipa can only render one content type per operation, but the server accepts both). Send a multipart body with these parts: `audio` (the audio file, required), `title` (text, optional), `description` (text, optional). Use this for direct file uploads from a browser or local script.


          Both content types hit the same handler, write to the same storage, and produce the same `item_id`.'
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UploadFromUrl'
        required: true
      responses:
        '200':
          description: Upload accepted; item created and queued for transcription
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadResponse'
        '400':
          description: 'Validation error — bad URL, missing required multipart field, etc. (`code: VALIDATION_ERROR`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '404':
          description: Dataset not found, or caller is not a member of the parent library (returned identically to avoid leaking existence)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '409':
          description: Dataset exists but is not configured for uploads (`content_type != 'uploads'`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '413':
          description: Uploaded / fetched file exceeds the per-upload size cap. Free tier is hard-capped at 400 MB; paid plans use the dataset's `max_file_size_mb` (default 500 MB).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '415':
          description: Unsupported audio format, or Content-Type is neither `multipart/form-data` nor `application/json`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '422':
          description: '`audio_url` is syntactically valid but unprocessable: DNS failure, non-2xx response, or resolves to a forbidden internal address (SSRF guard)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
      security:
      - BearerAuth: []
    servers:
    - url: https://www.audioscrape.com
      description: Production
  /api/items:
    get:
      tags:
      - Items
      summary: List audio items
      description: Universal listing across content types — podcast episodes, uploads, and future formats. Filter by `source_type`, `dataset_id`, or `library` (slug). Results are newest-first. Use this in place of `/api/episodes` when your integration needs to work with multiple content types.
      operationId: list_items
      parameters:
      - name: source_type
        in: query
        description: Filter by source type (`podcast_episode`, `upload`, `youtube`, ...). Omit for all types.
        required: false
        schema:
          type: string
      - name: dataset_id
        in: query
        description: Restrict to items in a specific dataset
        required: false
        schema:
          type: integer
          format: int64
      - name: library
        in: query
        description: Restrict to items in a specific library (by slug)
        required: false
        schema:
          type: string
      - name: limit
        in: query
        description: Max results (default 20, max 100)
        required: false
        schema:
          type: integer
          format: int64
      - name: offset
        in: query
        description: Result offset for pagination
        required: false
        schema:
          type: integer
          format: int64
      responses:
        '200':
          description: Items ordered by publish date descending
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ItemList'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '402':
          description: No active subscription (paid endpoint requires a subscription)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '403':
          description: Endpoint not available on the caller's plan
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '429':
          description: 'Monthly quota exhausted (response includes `usage: { current, limit }`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
      security:
      - BearerAuth: []
    servers:
    - url: https://www.audioscrape.com
      description: Production
  /api/items/{item_id}:
    get:
      tags:
      - Items
      summary: Get audio item
      description: Returns one item — podcast episode, upload, or any other source type. Heavy fields (transcript, entities) are opt-in via `?include=`. Equivalent to `GET /api/episodes/{id}` for podcast episodes, but works uniformly across all content types.
      operationId: get_item
      parameters:
      - name: item_id
        in: path
        description: Numeric item ID (works for any source_type)
        required: true
        schema:
          type: string
      - name: include
        in: query
        description: 'Comma-separated optional fields: `transcript`, `entities`.'
        required: false
        schema:
          type: string
      responses:
        '200':
          description: Item + parent podcast (when applicable), plus requested optional fields
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EpisodeDetail'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '402':
          description: No active subscription (paid endpoint requires a subscription)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '403':
          description: Endpoint not available on the caller's plan
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '404':
          description: Item not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '429':
          description: 'Monthly quota exhausted (response includes `usage: { current, limit }`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
      security:
      - BearerAuth: []
    servers:
    - url: https://www.audioscrape.com
      description: Production
  /api/items/{item_id}/transcript:
    get:
      tags:
      - Items
      summary: Get item transcript
      description: Returns the transcript on its own — segments + speaker list — for any item, regardless of source type.
      operationId: get_item_transcript
      parameters:
      - name: item_id
        in: path
        description: Numeric item ID
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Transcript segments + speaker list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transcript'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '402':
          description: No active subscription (paid endpoint requires a subscription)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '403':
          description: Endpoint not available on the caller's plan
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '404':
          description: Item not found or has no transcript
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '429':
          description: 'Monthly quota exhausted (response includes `usage: { current, limit }`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
      security:
      - BearerAuth: []
    servers:
    - url: https://www.audioscrape.com
      description: Production
components:
  schemas:
    EntityRef:
      type: object
      required:
      - name
      - entity_type
      - slug
      - mention_count
      properties:
        entity_type:
          type: string
        mention_count:
          type: integer
          format: int64
        name:
          type: string
        slug:
          type: string
    Item:
      type: object
      required:
      - id
      - title
      - slug
      - source_type
      - has_transcript
      properties:
        dataset_id:
          type:
          - integer
          - 'null'
          format: int64
        duration_seconds:
          type:
          - integer
          - 'null'
          format: int32
        has_transcript:
          type: boolean
        id:
          type: integer
          format: int64
        podcast:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/ItemPodcastRef'
            description: Reference to the podcast this item is part of, if applicable.
        publish_date:
          type:
          - string
          - 'null'
        slug:
          type: string
        source_type:
          type: string
          description: '`podcast_episode`, `upload`, `youtube`, etc.'
        title:
          type: string
    ApiErrorBody:
      type: object
      required:
      - code
      - message
      properties:
        code:
          type: string
          description: Stable machine-readable error code (UPPERCASE_SNAKE_CASE).
          example: SEARCH_LIMIT_EXCEEDED
        message:
          type: string
          description: Human-readable error message.
          example: Monthly search limit reached
        usage:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/UsageInfo'
            description: Present on rate-limit / quota errors. Omitted otherwise.
    UploadResponse:
      type: object
      required:
      - success
      - item_id
      - message
      properties:
        duplicate_of:
          type:
          - integer
          - 'null'
          format: int64
          description: 'Set when the bytes matched a recording already in the workspace:

            nothing was stored or transcribed, no minutes were used, and

            `item_id` is the existing recording.'
        item_id:
          type: integer
          format: int64
          description: 'ID of the newly-created item. Fetch full metadata at `GET /api/items/{id}`.

            When `duplicate_of` is set, this is that existing item.'
        message:
          type: string
          description: Human-readable status message (e.g. `"queued for transcription"`).
        success:
          type: boolean
    EpisodeDetail:
      type: object
      required:
      - episode
      - entities
      properties:
        entities:
          type: array
          items:
            $ref: '#/components/schemas/EntityRef'
        episode:
          $ref: '#/components/schemas/EpisodeFull'
        podcast:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/PodcastRef'
            description: 'Present for podcast episodes; `null` for uploaded items (which have no

              parent podcast).'
        transcript:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/Transcript'
    ItemPodcastRef:
      type: object
      required:
      - id
      - title
      - slug
      properties:
        id:
          type: integer
          format: int64
        slug:
          type: string
        title:
          type: string
    UsageInfo:
      type: object
      required:
      - current
      - limit
      properties:
        current:
          type: integer
          format: int64
          description: Current usage value (e.g., calls consumed this period).
        limit:
          type: integer
          format: int64
          description: Configured limit for the period.
    PodcastRef:
      type: object
      required:
      - id
      - title
      - slug
      properties:
        id:
          type: integer
          format: int64
        image_url:
          type:
          - string
          - 'null'
        slug:
          type: string
        title:
          type: string
    UploadFromUrl:
      type: object
      description: 'JSON body for URL-based upload. Use this when the audio is already

        hosted somewhere reachable from the public internet (S3 presigned URL,

        CDN, your own server). Audioscrape downloads it and stores a copy so

        transcription, indexing, and playback work even if your URL later

        becomes unavailable.'
      required:
      - audio_url
      properties:
        audio_url:
          type: string
          description: 'Publicly reachable `https://` URL of the audio file. Must NOT

            resolve to a private / internal IP range (SSRF guard).'
          example: https://files.example.com/recording.mp3
        content_type:
          type:
          - string
          - 'null'
          description: 'What the audio IS (e.g. `phone_call`). Drives the Details panel,

            speaker-label suggestions, and processing hints. See GH#35.'
        derive_title:
          type:
          - boolean
          - 'null'
          description: 'GH#617: opt in to derived titles (cleaned filename placeholder +

            transcript-derived title from the pipeline). Default OFF on the API:

            the title you send — or the file''s own name — is treated as your

            deliberate choice and never rewritten.'
        description:
          type:
          - string
          - 'null'
        metadata:
          description: 'Free-form, type-shaped metadata bag (descriptive fields + processing

            hints like num_speakers). Must be a JSON object. Stored on `items.metadata`.'
        title:
          type:
          - string
          - 'null'
    EpisodeFull:
      type: object
      required:
      - id
      - title
      - slug
      - description
      - publish_date
      - processing_status
      properties:
        description:
          type: string
        duration_seconds:
          type:
          - integer
          - 'null'
          format: int32
        enclosure_url:
          type:
          - string
          - 'null'
        id:
          type: integer
          format: int64
        processing_status:
          type: string
          description: 'Pipeline lifecycle of this item: `queued` | `processing` |

            `completed` | `completed_no_speech` | `failed` | `cancelled`, or

            `not_transcribed` for catalog items never queued for transcription.

            `completed_no_speech` means processing finished and the audio

            contained no speech, so no transcript will ever exist: stop polling

            for one (GH#435).'
        publish_date:
          type: string
        slug:
          type: string
        title:
          type: string
    ItemList:
      type: object
      required:
      - items
      - total
      - limit
      - offset
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
        limit:
          type: integer
          format: int64
        offset:
          type: integer
          format: int64
        total:
          type: integer
          format: int64
    TranscriptPartial:
      type: object
      required:
      - pieces_done
      - pieces_total
      - seconds_transcribed
      - seconds_total
      - speakers_final
      properties:
        pieces_done:
          type: integer
          format: int32
        pieces_total:
          type: integer
          format: int32
        seconds_total:
          type: integer
          format: int64
        seconds_transcribed:
          type: integer
          format: int64
        speakers_final:
          type: boolean
    TranscriptSegment:
      type: object
      required:
      - text
      - start
      - end
      properties:
        end:
          type: number
          format: double
        speaker:
          type:
          - string
          - 'null'
        start:
          type: number
          format: double
        text:
          type: string
    Transcript:
      type: object
      required:
      - segments
      - speakers
      - total_segments
      properties:
        partial:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/TranscriptPartial'
            description: 'Present (with HTTP 206) when the recording is still being

              transcribed in parts and `segments` covers only the finished ones.

              Speaker labels are provisional until the response is a plain 200.'
        segments:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptSegment'
        speakers:
          type: array
          items:
            type: string
        total_segments:
          type: integer
          minimum: 0
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key, format `sk_<base64(32 random bytes)>`
      description: 'Workspace-scoped API key. Pass as `Authorization: Bearer <key>`. The `?api_key=<key>` query parameter is deprecated: a key in a URL ends up in browser history, proxy logs and Referer headers.'
x-refined-from:
- audioscrape-com-openapi.json
- audioscrape-com-openapi.json