> ## Documentation Index
> Fetch the complete documentation index at: https://docs.timeless.day/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload media

> Upload an audio or video file for processing. The request body should be the raw binary file content — not multipart form data. Metadata is passed as query parameters.

After uploading, the file is queued for transcription and analysis. Use the returned meeting ID to check the status via List meetings.

<Note>
  The upload endpoint has a stricter rate limit of 10 requests per minute.
</Note>


## OpenAPI

````yaml PUT /meetings/upload
openapi: 3.1.0
info:
  title: Timeless Public API
  version: 0.1.0
  description: >-
    The Timeless API is a REST API served over HTTPS. All requests and responses
    use JSON, and all endpoints require authentication.
servers:
  - url: https://api.timeless.day/v1
    description: Production
security:
  - HTTPBearer: []
tags:
  - name: meetings
    description: Retrieve meetings, recordings, and transcripts.
  - name: rooms
    description: Retrieve rooms that group related meetings.
  - name: documents
    description: Retrieve AI-generated meeting documents.
  - name: upload
    description: Upload audio or video files for transcription.
  - name: webhooks
    description: Manage webhook subscriptions for event notifications.
paths:
  /meetings/upload:
    put:
      tags:
        - upload
      summary: Upload media
      description: >-
        Upload an audio or video file for processing. The request body should be
        the raw binary file content — not multipart form data. Metadata is
        passed as query parameters.


        After uploading, the file is queued for transcription and analysis. Use
        the returned meeting ID to check the status via List meetings.
      operationId: create_upload_v1_meetings_upload_put
      parameters:
        - name: title
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                maxLength: 500
              - type: 'null'
            title: Title
          description: Optional title for the recording (max 500 characters).
        - name: language
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                maxLength: 10
              - type: 'null'
            title: Language
          description: Language code for transcription (e.g., `en`, `es`).
          example: en
        - name: content-type
          in: header
          required: true
          schema:
            type: string
            title: Content-Type
          description: >-
            The MIME type of the uploaded file.


            **Supported audio types:** `audio/mpeg`, `audio/mp4`, `audio/wav`,
            `audio/webm`, `audio/ogg`, `audio/aac`, `audio/flac`


            **Supported video types:** `video/mp4`, `video/webm`, `video/ogg`,
            `video/quicktime`
      responses:
        '201':
          description: Upload accepted for processing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadResponse'
              example:
                id: mtg_abc123
                status: processing
        '401':
          description: Authentication required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - HTTPBearer: []
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >-
            curl -X PUT
            "https://api.timeless.day/v1/meetings/upload?title=Team%20sync&language=en"
            \
              -H "Authorization: Bearer YOUR_API_TOKEN" \
              -H "Content-Type: audio/mpeg" \
              --data-binary @recording.mp3
        - lang: python
          label: Python
          source: |-
            import requests

            with open("recording.mp3", "rb") as f:
                response = requests.put(
                    "https://api.timeless.day/v1/meetings/upload",
                    headers={
                        "Authorization": "Bearer YOUR_API_TOKEN",
                        "Content-Type": "audio/mpeg",
                    },
                    params={"title": "Team sync", "language": "en"},
                    data=f,
                )

            upload = response.json()
        - lang: javascript
          label: JavaScript
          source: |-
            const fs = require("fs");

            const body = fs.readFileSync("recording.mp3");

            const response = await fetch(
              "https://api.timeless.day/v1/meetings/upload?title=Team%20sync&language=en",
              {
                method: "PUT",
                headers: {
                  Authorization: "Bearer YOUR_API_TOKEN",
                  "Content-Type": "audio/mpeg",
                },
                body,
              }
            );

            const upload = await response.json();
        - lang: php
          label: PHP
          source: |-
            <?php

            $file = fopen("recording.mp3", "r");
            $body = fread($file, filesize("recording.mp3"));
            fclose($file);

            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => "https://api.timeless.day/v1/meetings/upload?title=Team%20sync&language=en",
                CURLOPT_CUSTOMREQUEST => "PUT",
                CURLOPT_POSTFIELDS => $body,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HTTPHEADER => [
                    "Authorization: Bearer YOUR_API_TOKEN",
                    "Content-Type: audio/mpeg",
                ],
            ]);

            $response = curl_exec($ch);
            curl_close($ch);

            $upload = json_decode($response, true);
        - lang: go
          label: Go
          source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tfile, _ := os.Open(\"recording.mp3\")\n\tdefer file.Close()\n\n\treq, _ := http.NewRequest(\n\t\t\"PUT\",\n\t\t\"https://api.timeless.day/v1/meetings/upload?title=Team%20sync&language=en\",\n\t\tfile,\n\t)\n\treq.Header.Set(\"Authorization\", \"Bearer YOUR_API_TOKEN\")\n\treq.Header.Set(\"Content-Type\", \"audio/mpeg\")\n\n\tresp, _ := http.DefaultClient.Do(req)\n\tdefer resp.Body.Close()\n\n\tbody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(string(body))\n}"
        - lang: java
          label: Java
          source: |-
            import java.net.URI;
            import java.net.http.HttpClient;
            import java.net.http.HttpRequest;
            import java.net.http.HttpResponse;
            import java.nio.file.Path;

            HttpClient client = HttpClient.newHttpClient();

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.timeless.day/v1/meetings/upload?title=Team%20sync&language=en"))
                .header("Authorization", "Bearer YOUR_API_TOKEN")
                .header("Content-Type", "audio/mpeg")
                .PUT(HttpRequest.BodyPublishers.ofFile(Path.of("recording.mp3")))
                .build();

            HttpResponse<String> response = client.send(
                request, HttpResponse.BodyHandlers.ofString()
            );

            System.out.println(response.body());
        - lang: ruby
          label: Ruby
          source: >-
            require "uri"

            require "net/http"


            url =
            URI("https://api.timeless.day/v1/meetings/upload?title=Team%20sync&language=en")


            http = Net::HTTP.new(url.host, url.port)

            http.use_ssl = true


            request = Net::HTTP::Put.new(url)

            request["Authorization"] = "Bearer YOUR_API_TOKEN"

            request["Content-Type"] = "audio/mpeg"

            request.body = File.binread("recording.mp3")


            response = http.request(request)

            puts response.read_body
components:
  schemas:
    UploadResponse:
      properties:
        id:
          type: string
          title: Id
          description: >-
            The meeting ID for the uploaded recording. Use this to track
            processing status.
          example: mtg_abc123
        status:
          type: string
          const: processing
          title: Status
          default: processing
          description: Always `processing` on successful upload.
      type: object
      required:
        - id
      title: UploadResponse
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: not_found
            message:
              type: string
              example: Resource not found
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  message:
                    type: string
          required:
            - code
            - message
      required:
        - error
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer
      description: >-
        API token from your [Timeless
        dashboard](https://my.timeless.day/api-token).

````