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

# List Posts

> Retrieve a paginated list of posts from your workspaces

## List Posts

Retrieves a paginated list of posts from all workspaces that the authenticated user has access to. Posts are returned in reverse chronological order (newest first). Use `include_comments=true` to attach all comments for each post, including their associated contact info.

### Request

<ParamField query="page" type="integer" default="1">
  Page number for pagination
</ParamField>

<ParamField query="per_page" type="integer" default="100" max="100">
  Number of posts per page (maximum 100)
</ParamField>

<ParamField query="include_comments" type="boolean" default="false">
  When true, includes all comments associated with each post, including their contact info (CRM contact)
</ParamField>

<RequestExample>
  ```bash theme={null}
  curl -X GET "https://postsyncer.com/api/v1/posts?page=1&per_page=20&include_comments=true" \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```
</RequestExample>

### Response

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

<ResponseField name="current_page" type="integer">
  Current page number
</ResponseField>

<ResponseField name="last_page" type="integer">
  Last page number
</ResponseField>

<ResponseField name="per_page" type="integer">
  Number of items per page
</ResponseField>

<ResponseField name="total" type="integer">
  Total number of posts
</ResponseField>

<ResponseField name="from" type="integer">
  Starting post number for current page
</ResponseField>

<ResponseField name="to" type="integer">
  Ending post number for current page
</ResponseField>

<ResponseField name="data[].comments" type="array">
  When `include_comments=true`, each post includes a `comments` array. Each comment has `id`, `content`, `author_name`, `platform`, `created_at`, and a `contact` object with CRM contact info (name, username, profile\_url, etc.) when available.
</ResponseField>

<ResponseExample>
  ```json theme={null}
  {
    "data": [
      {
        "id": 123,
        "content": [
          {
            "text": "Exciting news! We've just launched our winter collection ❄️",
            "media": [
              {
                "id": 1594,
                "name": "file_example_MP4_1920_18MG.mp4",
                "url": "https://postsyncer-local.c6c56f7fb91dd557ca29aa14c4e7d980.r2.cloudflarestorage.com/media/12/5ee789eb-c88c-4af2-8449-54c6c0561f31.mp4?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=a4bcd089276d5d5b77253aa9b13fe59c%2F20250705%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20250705T131116Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1800&X-Amz-Signature=0ef23b86009e4cac6e160863a4b91f15b78270e5524f328fb764a9f22bdaffe3",
                "type": "video/mp4",
                "size": 17839845
              }
            ]
          }
        ],
        "status": "PUBLISHED",
        "posted_on": ["2023-12-15 02:00 PM"],
        "scheduled_at": null,
        "repeatable": false,
        "repeatable_times": null,
        "repeatable_gap": null,
        "repeatable_gap_unit": null,
        "remaining_posts": null,
        "workspace": {
          "id": 12,
          "name": "abdulmejidshemsuawel",
          "slug": "abdulmejidshemsuawel",
          "type": "PERSONAL",
          "logo": null,
          "timezone": "Africa/Addis_Ababa",
          "language": "en"
        },
        "labels": [
          {
            "id": 1,
            "name": "Product Launch",
            "color": "#ff0000"
          }
        ],
        "platforms": [
          {
            "platform": "twitter",
            "posted_on": ["2025-07-05 12:36"],
            "status": "PUBLISHED",
            "settings": {
              "for_super_followers_only": false,
              "reply_settings": "everyone",
              "quote_tweet_id": null,
              "reply": {
                  "in_reply_to_tweet_id": null
              },
              "community_id": null,
              "share_with_followers": true,
              "text": null,
              "poll": {
                  "enabled": false
              }
            },
            "analytics": {
                "comments": 8,
                "likes": 42,
                "shares": 8,
                "impressions": 1250,
                "quotes": 2,
                "saves": 12,
                "engagement_rate": 4.4
            }
          }
        ],
        "auto_plug": null,
        "created_at": "2023-12-01 09:30 AM",
        "updated_at": "2023-12-15 02:00 PM",
        "comments": []
      }
    ],
    "current_page": 1,
    "last_page": 5,
    "per_page": 20,
    "total": 95,
    "from": 1,
    "to": 20,
    "links": [
      {
          "url": "https://postsyncer.com/api/v1/posts?page=1",
          "label": "&laquo; Previous",
          "active": false
      },
      {
          "url": "https://postsyncer.com/api/v1/posts?page=1",
          "label": "1",
          "active": false
      },
      {
          "url": "https://postsyncer.com.test/api/v1/posts?page=2",
          "label": "2",
          "active": true
      }
      ...
    ]
  }
  ```
</ResponseExample>

### Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://postsyncer.com/api/v1/posts?page=1&per_page=20&include_comments=true" \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios');

  const getPosts = async (page = 1, perPage = 20) => {
    try {
      const response = await axios.get('https://postsyncer.com/api/v1/posts', {
        headers: {
          'Authorization': 'Bearer YOUR_API_TOKEN'
        },
        params: {
          page: page,
          per_page: perPage
        }
      });
      
      console.log('Posts:', response.data);
      return response.data;
    } catch (error) {
      console.error('Error fetching posts:', error.response?.data || error.message);
    }
  };

  getPosts();
  ```

  ```php PHP theme={null}
  <?php

  $page = 1;
  $perPage = 20;

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "https://postsyncer.com/api/v1/posts?page={$page}&per_page={$perPage}");
  curl_setopt($ch, CURLOPT_HTTPGET, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer YOUR_API_TOKEN'
  ]);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($httpCode === 200) {
      $posts = json_decode($response, true);
      echo "Found " . $posts['total'] . " posts";
  } else {
      echo "Error: " . $response;
  }
  ?>
  ```

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

  headers = {
      'Authorization': 'Bearer YOUR_API_TOKEN'
  }

  params = {
      'page': 1,
      'per_page': 20
  }

  response = requests.get(
      'https://postsyncer.com/api/v1/posts',
      headers=headers,
      params=params
  )

  if response.status_code == 200:
      posts = response.json()
      print(f"Found {posts['total']} posts")
      for post in posts['data']:
          print(f"Post {post['id']}: {post['content'][0]['text'][:50]}...")
  else:
      print(f"Error: {response.status_code}")
      print(response.text)
  ```
</CodeGroup>

### Error Codes

<ResponseField name="401" type="Unauthorized">
  Missing or invalid API token
</ResponseField>

<ResponseField name="403" type="Forbidden">
  Token does not have 'posts' permission
</ResponseField>
