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

# Bulk Post

> Lên lịch hàng loạt bài đăng với tệp CSV

export const XByoNotice = () => <Info>
  <strong>Targeting X/Twitter?</strong> Starting March 31, 2026, all X operations require your own API credentials. After linking X via OAuth, include these 2 headers in your request:
  <br /><br />
  <code>X-Twitter-OAuth1-Api-Key</code> — Your API Key (Consumer Key)<br />
  <code>X-Twitter-OAuth1-Api-Secret</code> — Your API Key Secret (Consumer Secret)
  <br /><br />
  <strong>One-time setup per Ayrshare account.</strong> You create one X Developer App and reuse the same API Key and Secret across every sub-profile / end-user you link. You do <em>not</em> create a new app per customer.
  <br /><br />
  Not linked yet? See the <a href="/dashboard/connect-social-accounts/x-twitter-byo-keys">full setup guide</a> to connect your X account.
  <br /><br />
  Your keys are never logged or stored by Ayrshare.
</Info>;

export const PlansAvailable = ({plans = [], maxPackRequired}) => {
  let displayPlans = plans;
  if (plans && plans.length === 1) {
    const lowerCasePlan = plans[0].toLowerCase();
    if (lowerCasePlan === "business") {
      displayPlans = ["Launch", "Business", "Enterprise"];
    } else if (lowerCasePlan === "premium") {
      displayPlans = ["Premium", "Launch", "Business", "Enterprise"];
    }
  }
  return <Note>
Available on {displayPlans.length === 1 ? "the " : ""}
{displayPlans.join(", ").replace(/\b\w/g, l => l.toUpperCase())}{" "}
{displayPlans.length > 1 ? "plans" : "plan"}.

{maxPackRequired && <span onClick={() => window.open('https://www.ayrshare.com/docs/additional/maxpack', '_self')} className="flex items-center mt-2 cursor-pointer">
 <span className="px-1.5 py-0.5 rounded text-sm" style={{
    backgroundColor: '#C264B6',
    color: 'white',
    fontSize: '12px'
  }}>
   Max Pack required
 </span>
</span>}
</Note>;
};

<PlansAvailable plans={["premium"]} maxPackRequired={false} />

<XByoNotice />

Lên lịch hàng loạt bài đăng bằng tệp CSV (Comma Separated Values) chứa dữ liệu các bài đăng.
Content-Type phải là `multipart/form-data`.

<Warning>
  Chúng tôi khuyến nghị sử dụng [endpoint Post](/apis/post/post) trực tiếp thay vì phương thức bulk này để
  lên lịch bài đăng. Endpoint trực tiếp cung cấp bộ tính năng toàn diện hơn và khả năng
  gỡ lỗi dễ dàng hơn.
</Warning>

## Tham số Header

<ParamField header="Authorization" type="string" required>
  Định dạng: `Authorization: Bearer API_KEY`. Xem [tổng quan API](/apis/overview#authorization) để biết thêm
  thông tin.
</ParamField>

<ParamField header="Profile-Key" type="string">
  Profile Key của một user profile.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `Content-Type: multipart/form-data`
</ParamField>

## Tham số Body

<ParamField path="file" type="object">
  Tệp CSV multipart form-data chứa các bài đăng đã lên lịch. Xem bên dưới để biết [mẫu CSV](#csv-template).
</ParamField>

## Ví dụ Request

Một multipart form-data chứa tệp CSV các bài đăng sẽ lên lịch chúng cho một ngày trong tương lai.

Tệp CSV chứa các trường sau (mẫu bên dưới) và đều bắt buộc:

<ul class="custom-bullets">
  <li>`post`: Nội dung bài đăng.</li>
  <li>`platforms`: Danh sách các nền tảng phân tách bằng dấu phẩy, ví dụ: "twitter, facebook, instagram".</li>
  <li>`mediaUrls`: URL của phương tiện, chẳng hạn như hình ảnh hoặc video để bao gồm trong bài đăng.</li>

  <li>
    `scheduleDate`: Thời gian lên lịch bài đăng theo định dạng UTC. Ví dụ, dùng định dạng
    `YYYY-MM-DDThh:mm:ssZ` và gửi dưới dạng `2026-07-08T12:30:00Z`. Vui lòng xem
    [utctime](https://www.utctime.net/) để biết thêm ví dụ.
  </li>
</ul>

<Warning>
  Không gửi các bài đăng trùng lặp cách nhau chưa đến hai ngày.

  Nếu scheduleDate của hai bài đăng có nội dung giống hệt nhau cách nhau chưa đến ba ngày, bài đăng thứ hai sẽ bị từ chối khi scheduleDate xảy ra.
  Điều này nhằm bảo vệ tài khoản của bạn tại các mạng xã hội; họ có thể tạm ngưng hoặc shadow-ban các tài khoản đăng trùng lặp thường xuyên.
</Warning>

## Mẫu CSV

Tải xuống mẫu và lưu dưới dạng tệp .csv.

[Mẫu CSV Ayrshare](https://img.ayrshare.com/012/Ayrshare_CSV_Template.csv)

<RequestExample>
  ```bash cURL theme={"system"}
  curl \
  -H "Authorization: Bearer API_KEY" \
  -H 'Content-Type: multipart/form-data' \
  -F 'file=@"./Ayrshare CSV Template.csv"' \
  -X POST https://api.ayrshare.com/api/post/bulk
  ```

  ```javascript JavaScript theme={"system"}
  const API_KEY = "API_KEY";
  const FormData = require("form-data");
  const fs = require("fs");

  const formData = new FormData();
  formData.append("file", fs.createReadStream("./Ayrshare CSV Template.csv"));

  fetch("https://api.ayrshare.com/api/post/bulk", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      ...formData.getHeaders()
    },
    body: formData
  })
    .then((res) => res.json())
    .then((data) => {
      console.log(JSON.stringify(data));
    })
    .catch((error) => {
      console.log(error);
    });
  ```

  ```python Python theme={"system"}
  import requests

  API_KEY = "API_KEY"

  # Open the CSV file in binary read mode
  with open('./Ayrshare CSV Template.csv', 'rb') as file:
      # Prepare the files dictionary for the multipart/form-data request
      files = {'file': file}

      # Set up the authorization header
      headers = {'Authorization': f'Bearer {API_KEY}'}

      try:
          # Make the POST request to the API
          response = requests.post(
              'https://api.ayrshare.com/api/post/bulk',
              headers=headers,
              files=files
          )

          # Parse and print the JSON response
          data = response.json()
          print(data)

      except Exception as e:
          print(f"Error: {e}")
  ```
</RequestExample>

<ResponseExample>
  ```javascript 200: OK Ví dụ với hai bài đăng đã lên lịch. theme={"system"}
  {
      "status": "success",
      "posts": [
          {
              "status": "scheduled",
              "scheduleDate": "4/6/21 12:50",
              "id": "X3uTExuEJhyM3u8wCRsA",
              "post": "A great post"
          },
          {
              "status": "scheduled",
              "scheduleDate": "4/6/21 13:00",
              "id": "8RGrekuxMnVa7lVnARFm",
              "post": "An even better post"
          }
      ]
  }
  ```
</ResponseExample>
