> ## 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 Published Projects

> List your published posts with optional platform filtering and cursor-based pagination, including per-platform status and analytics

# List Published Projects

Retrieve a paginated list of your published posts across YouTube, TikTok, and
Instagram. Each entry includes per-platform delivery status, post URLs, and
analytics where available.

<Note>
  This endpoint requires authentication.
</Note>

## Authentication

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

## Query Parameters

<ParamField query="platform" type="string">
  Filter by platform. Allowed values: `youtube`, `tiktok`, `instagram`.
</ParamField>

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

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

## Response

<ResponseField name="data" type="array">
  Array of publication objects

  <Expandable title="Publication Object" defaultOpen>
    <ResponseField name="id" type="string">
      Unique identifier of the publication
    </ResponseField>

    <ResponseField name="projectId" type="string">
      The unique identifier of the underlying project
    </ResponseField>

    <ResponseField name="publishedAt" type="string">
      ISO 8601 timestamp of when the publication was published or is scheduled
      to publish
    </ResponseField>

    <ResponseField name="scheduled" type="boolean">
      `true` if the publication was scheduled for a future time
    </ResponseField>

    <ResponseField name="status" type="string">
      Overall publication status: `published`, `scheduled`, `processing`, or
      `failed`
    </ResponseField>

    <ResponseField name="project" type="object">
      Minimal project metadata

      <Expandable title="Project">
        <ResponseField name="id" type="string">
          Project UUID
        </ResponseField>

        <ResponseField name="title" type="string">
          Project title
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="posts" type="array">
      Array of per-platform post objects

      <Expandable title="Post Object">
        <ResponseField name="platform" type="string">
          Platform identifier: `youtube`, `tiktok`, or `instagram`
        </ResponseField>

        <ResponseField name="platformPostId" type="string">
          The post ID assigned by the upstream platform
        </ResponseField>

        <ResponseField name="platformPostUrl" type="string">
          Public URL of the post on the platform
        </ResponseField>

        <ResponseField name="publishStatus" type="string">
          Per-platform delivery status: `published`, `scheduled`, `processing`,
          or `failed`
        </ResponseField>

        <ResponseField name="syncStatus" type="string">
          Analytics sync status: `synced`, `pending`, or `failed`
        </ResponseField>

        <ResponseField name="error" type="string">
          Error message if the post failed to publish, otherwise `null`
        </ResponseField>

        <ResponseField name="analytics" type="object">
          Platform analytics (available once `syncStatus` is `synced`)

          <Expandable title="Analytics">
            <ResponseField name="views" type="number">
              Total views
            </ResponseField>

            <ResponseField name="likes" type="number">
              Total likes
            </ResponseField>

            <ResponseField name="comments" type="number">
              Total comments
            </ResponseField>

            <ResponseField name="shares" type="number">
              Total shares
            </ResponseField>

            <ResponseField name="impressions" type="number">
              Total impressions
            </ResponseField>

            <ResponseField name="reach" type="number">
              Unique accounts reached
            </ResponseField>

            <ResponseField name="clicks" type="number">
              Total link clicks
            </ResponseField>

            <ResponseField name="engagementRate" type="number">
              Engagement rate as a decimal (e.g. `0.125` = 12.5%)
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="pagination" type="object">
  Cursor-based pagination metadata

  <Expandable title="Pagination" defaultOpen>
    <ResponseField name="nextCursor" type="string">
      Cursor to pass as the `cursor` query parameter to fetch the next page.
      `null` or omitted when there are no more results.
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://api.submagic.co/v1/projects/published?platform=youtube&limit=25" \
    -H "x-api-key: sk-your-api-key-here"
  ```

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

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

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

  // Fetch first page of YouTube publications
  const page = await listPublishedProjects({ platform: "youtube", limit: 25 });

  // Fetch next page
  if (page.pagination.nextCursor) {
    const nextPage = await listPublishedProjects({
      platform: "youtube",
      limit: 25,
      cursor: page.pagination.nextCursor,
    });
  }
  ```

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

  def list_published_projects(platform=None, limit=None, cursor=None):
      url = 'https://api.submagic.co/v1/projects/published'
      headers = {
          'x-api-key': 'sk-your-api-key-here'
      }
      params = {}
      if platform:
          params['platform'] = platform
      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['data'])} publications")
      return data

  # Fetch first page of YouTube publications
  page = list_published_projects(platform='youtube', limit=25)

  # Fetch next page
  next_cursor = page.get('pagination', {}).get('nextCursor')
  if next_cursor:
      next_page = list_published_projects(
          platform='youtube',
          limit=25,
          cursor=next_cursor
      )
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "data": [
      {
        "id": "pub_8f3b4c2e-1a9d-4e5f-9b7c-2a4d6e8f1c3b",
        "projectId": "550e8400-e29b-41d4-a716-446655440000",
        "publishedAt": "2026-04-28T12:34:56.000Z",
        "scheduled": false,
        "status": "published",
        "project": {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "title": "How I Doubled My Revenue in 30 Days"
        },
        "posts": [
          {
            "platform": "youtube",
            "platformPostId": "dQw4w9WgXcQ",
            "platformPostUrl": "https://youtube.com/watch?v=dQw4w9WgXcQ",
            "publishStatus": "published",
            "syncStatus": "synced",
            "error": null,
            "analytics": {
              "views": 1234,
              "likes": 56,
              "comments": 7,
              "shares": 2,
              "impressions": 5000,
              "reach": 800,
              "clicks": 120,
              "engagementRate": 0.125
            }
          }
        ]
      }
    ],
    "pagination": {
      "nextCursor": "eyJpZCI6InB1Yl83YjJjM2Q0ZSJ9"
    }
  }
  ```

  ```json 200 OK (empty) theme={null}
  {
    "data": [],
    "pagination": {
      "nextCursor": null
    }
  }
  ```
</ResponseExample>

## Error Responses

<ResponseField name="400 Validation Error" type="object">
  ```json theme={null}
  {
    "error": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "platform",
        "message": "Must be one of: youtube, tiktok, instagram",
        "value": "facebook"
      }
    ]
  }
  ```
</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>
