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

# List User Media

> List the media files in your library

# List User Media

Retrieve a paginated list of media files from your library. You can filter by media type and control pagination using cursor-based navigation.

<Note>
  This endpoint requires authentication and has a rate limit of 500 requests per
  hour.
</Note>

## Authentication

<ParamField header="x-api-key" type="string" required>
  Your Submagic API key starting with `sk-`
</ParamField>

## Query Parameters

<ParamField query="type" type="string">
  Filter by media type. Allowed values: `VIDEO`, `AUDIO`, `IMAGE`.
</ParamField>

<ParamField query="limit" type="number">
  Number of items to return per page (1-100). Defaults to `50`.
</ParamField>

<ParamField query="cursor" type="string">
  UUID cursor for pagination. Pass the `nextCursor` value from a previous
  response to fetch the next page of results.
</ParamField>

## Response

<ResponseField name="items" type="array">
  Array of user media objects

  <Expandable title="User Media Object" defaultOpen>
    <ResponseField name="id" type="string">
      Unique identifier for the media file (UUID format)
    </ResponseField>

    <ResponseField name="type" type="string">
      Media type: `VIDEO`, `AUDIO`, or `IMAGE`
    </ResponseField>

    <ResponseField name="fileName" type="string">
      Original file name of the uploaded media
    </ResponseField>

    <ResponseField name="url" type="string">
      URL to access the media file
    </ResponseField>

    <ResponseField name="metadata" type="object">
      File metadata that varies by media type

      <Expandable title="Metadata Fields">
        <ResponseField name="width" type="number">
          Width in pixels (VIDEO and IMAGE only)
        </ResponseField>

        <ResponseField name="height" type="number">
          Height in pixels (VIDEO and IMAGE only)
        </ResponseField>

        <ResponseField name="duration" type="number">
          Duration in seconds (VIDEO and AUDIO only)
        </ResponseField>

        <ResponseField name="fileSize" type="number">
          File size in bytes
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO 8601 timestamp when the media was uploaded
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  Whether there are more items available beyond this page
</ResponseField>

<ResponseField name="nextCursor" type="string">
  Cursor to pass as the `cursor` query parameter to fetch the next page.
  Only present when `hasMore` is `true`.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://api.submagic.co/v1/user-media?type=AUDIO&limit=10" \
    -H "x-api-key: sk-your-api-key-here"
  ```

  ```javascript JavaScript theme={null}
  const listUserMedia = async ({ type, limit, cursor } = {}) => {
    const params = new URLSearchParams();
    if (type) params.set("type", type);
    if (limit) params.set("limit", String(limit));
    if (cursor) params.set("cursor", cursor);

    const response = await fetch(
      `https://api.submagic.co/v1/user-media?${params}`,
      {
        headers: {
          "x-api-key": "sk-your-api-key-here",
        },
      }
    );

    const data = await response.json();
    console.log(`Fetched ${data.items.length} items`);
    return data;
  };

  // Fetch first page of audio files
  const page = await listUserMedia({ type: "AUDIO", limit: 10 });

  // Fetch next page
  if (page.hasMore) {
    const nextPage = await listUserMedia({
      type: "AUDIO",
      limit: 10,
      cursor: page.nextCursor,
    });
  }
  ```

  ```python Python theme={null}
  import requests

  def list_user_media(media_type=None, limit=None, cursor=None):
      url = 'https://api.submagic.co/v1/user-media'
      headers = {
          'x-api-key': 'sk-your-api-key-here'
      }
      params = {}
      if media_type:
          params['type'] = media_type
      if limit:
          params['limit'] = limit
      if cursor:
          params['cursor'] = cursor

      response = requests.get(url, headers=headers, params=params)
      data = response.json()

      print(f"Fetched {len(data['items'])} items")
      return data

  # Fetch first page of audio files
  page = list_user_media(media_type='AUDIO', limit=10)

  # Fetch next page
  if page['hasMore']:
      next_page = list_user_media(
          media_type='AUDIO',
          limit=10,
          cursor=page['nextCursor']
      )
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "items": [
      {
        "id": "88a08eec-712a-45d0-8d0b-3b631700cb3a",
        "type": "AUDIO",
        "fileName": "background-music.mp3",
        "url": "https://cdn.submagic.co/media/88a08eec-712a-45d0-8d0b-3b631700cb3a.mp3",
        "metadata": {
          "duration": 180.5,
          "fileSize": 4500000
        },
        "createdAt": "2024-01-10T08:00:00.000Z"
      },
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "type": "VIDEO",
        "fileName": "broll-clip.mp4",
        "url": "https://cdn.submagic.co/media/a1b2c3d4-e5f6-7890-abcd-ef1234567890.mp4",
        "metadata": {
          "width": 1920,
          "height": 1080,
          "duration": 12.3,
          "fileSize": 15000000
        },
        "createdAt": "2024-01-09T14:30:00.000Z"
      }
    ],
    "hasMore": true,
    "nextCursor": "f5e4d3c2-b1a0-9876-fedc-ba0987654321"
  }
  ```

  ```json 200 OK (empty) theme={null}
  {
    "items": [],
    "hasMore": false
  }
  ```
</ResponseExample>

## Error Responses

<ResponseField name="400 Validation Error" type="object">
  ```json theme={null}
  {
    "error": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "type",
        "message": "Must be one of: VIDEO, AUDIO, IMAGE",
        "value": "INVALID"
      }
    ]
  }
  ```
</ResponseField>

<ResponseField name="401 Unauthorized" type="object">
  ```json theme={null}
  {
    "error": "UNAUTHORIZED",
    "message": "Invalid or missing API key"
  }
  ```
</ResponseField>

<ResponseField name="429 Rate Limited" type="object">
  ```json theme={null}
  {
    "error": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests",
    "retryAfter": 30
  }
  ```
</ResponseField>

<ResponseField name="500 Server Error" type="object">
  ```json theme={null}
  {
    "error": "INTERNAL_SERVER_ERROR",
    "message": "An unexpected error occurred"
  }
  ```
</ResponseField>
