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

# Make

> Đăng lên mọi nền tảng từ một scenario Make (Integromat) bằng REST API của MADIAD Hub.

Make giao tiếp với MADIAD Hub qua module chung **HTTP → Make a request**, không cần cài app tuỳ chỉnh nào. Thêm module này vào bất kỳ scenario nào, bạn có thể đăng khi Google Sheet thay đổi, theo lịch, khi có form gửi về, hoặc theo bất kỳ sự kiện kích hoạt nào khác mà Make hỗ trợ.

<Note>
  Hướng dẫn này giả định bạn đã có API key và ít nhất một profile được kết nối. Nếu chưa, hãy làm [Bắt đầu nhanh](/vi/quickstart) trước (5 phút).
</Note>

## 1. Khối cơ bản: HTTP → Make a request

Mọi lệnh gọi bên dưới đều dùng chung một module là **HTTP → Make a request**. Các thiết lập chung:

| Trường         | Giá trị                                                  |
| -------------- | -------------------------------------------------------- |
| URL            | `https://api.madiad.com/v1/…` (endpoint theo loại media) |
| Method         | `POST`                                                   |
| Headers        | `Authorization: Bearer mdc_live_…`                       |
| Parse response | **Yes**, để phản hồi JSON được map vào các module sau    |

<Warning>
  Tạo **một API key riêng** cho Make (đặt tên `make` trong dashboard). Nếu bị lộ, bạn chỉ thu hồi đúng key đó mà không ảnh hưởng các tích hợp khác. Lưu key trong một biến scenario hoặc data store của Make thay vì dán vào từng module.
</Warning>

## 2. Đăng một bài chỉ có chữ

Thêm module **HTTP → Make a request**:

* **URL** là `https://api.madiad.com/v1/posts/text`
* **Method** là `POST`
* **Headers** là thêm `Authorization` = `Bearer mdc_live_…`
* **Body type** là `Raw`
* **Content type** là `application/json`
* **Request content**:

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "platforms": ["facebook", "linkedin", "x"],
  "caption": "Bài viết mới đã lên sóng, đọc ngay trên blog."
}
```

Bài chỉ có chữ dùng JSON. **Ảnh và video dùng hai định dạng khác nhau**, xem [Đăng file](#4-đăng-ảnh-hoặc-video).

## 3. Chống trùng lặp bằng Idempotency-Key

Make chạy lại một module khi gặp lỗi hoặc khi bạn thực thi lại scenario. Để tránh đăng trùng, thêm một header có giá trị ổn định cho mỗi mục. Hub sẽ coi lần lặp lại cùng key là cùng một yêu cầu.

Thêm header:

| Name              | Value                                                                                                                       |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `Idempotency-Key` | map một trường duy nhất cho mỗi bài và không bao giờ bị dùng lại: một cột UUID hoặc mã bản ghi, **không** dùng `Row number` |

Dùng một giá trị **duy nhất cho mỗi bài định đăng** và **không đổi khi thử lại chính bài đó**. Lựa chọn tốt: một UUID bạn sinh một lần rồi ghi ngược lại vào dòng dữ liệu, hoặc một hash của chính nội dung.

<Warning>
  **Tuyệt đối không dùng giá trị bị tái sử dụng.** Số dòng bảng tính sẽ dịch chuyển khi bạn xoá dòng, khiến nội dung hôm nay mang một key mà bài hôm qua đã chiếm. Khi gặp key đã dùng, Hub trả về kết quả **cũ** và không đăng gì cả, nên một key hỏng trông y hệt một bài đăng thành công. Hãy để ý header `Idempotent-Replayed: true`, và xem [Idempotency](/vi/concepts/idempotency).
</Warning>

## 4. Đăng ảnh hoặc video

**Ảnh** dùng `POST /v1/posts/photos`. Đặt **Body type** thành `Multipart/form-data`, lặp lại `platforms[]` một lần cho mỗi nền tảng, và đính kèm ảnh qua một trường **file** map từ module trước (ví dụ *Google Drive → Download a file*, hoặc *HTTP → Get a file*):

| Tên trường    | Kiểu | Giá trị                                 |
| ------------- | ---- | --------------------------------------- |
| `profile_id`  | Text | `prof_…`                                |
| `platforms[]` | Text | `instagram`                             |
| `platforms[]` | Text | `facebook`                              |
| `caption`     | Text | `Ra mắt hương vị mới hôm nay`           |
| `photos[]`    | File | `data` + `file name` từ module download |

Đã có sẵn URL ảnh công khai thay vì file? Bỏ qua bước tải lên và gửi `photo_urls[]` dưới dạng **Raw JSON**, xem [Đăng ảnh bằng URL](/vi/concepts/posts#đăng-ảnh-bằng-url).

**Video** dùng `POST /v1/posts/video`, chỉ nhận JSON chứ không nhận file tải lên. Đặt **Body type** thành `Raw` / `application/json` và truyền một `video_url` công khai:

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "platforms": ["tiktok", "youtube"],
  "video_url": "https://cdn.example.com/launch.mp4"
}
```

## 5. Xử lý phản hồi bất đồng bộ

Bài chỉ có chữ hoặc bài ảnh tới các nền tảng nhanh thường trả về `"status": "completed"`. **Video là bất đồng bộ**, nó trả về `"status": "processing"` và một `request_id`. Có hai cách hoàn tất:

**Poll** là thêm module **Sleep**, rồi một module **HTTP → Make a request** khác:

```
GET https://api.madiad.com/v1/posts/status?request_id={{request_id}}
```

Bọc nó trong một **Repeater** và dừng khi `status` là `completed`, `partial`, hoặc `failed`.

**Webhook (khuyến nghị)** là thêm module **Custom webhook** trong Make, sao chép địa chỉ của nó, và đăng ký trong dashboard tại [hub.madiad.com/dashboard/webhooks](https://hub.madiad.com/dashboard/webhooks) cho sự kiện `post.completed`. Hub ký mỗi lần gửi bằng HMAC-SHA256, hãy xác thực trước khi tin vào payload. Xem [Webhooks](/vi/concepts/webhooks).

## 6. Đọc kết quả theo từng nền tảng

Khi bật **Parse response**, bạn map thẳng phản hồi. Một bài đăng có thể thành công một phần, hãy rẽ nhánh theo `success` của từng nền tảng thay vì chỉ nhìn `status` tổng:

```json theme={null}
{
  "status": "partial",
  "results": {
    "facebook": { "success": true,  "url": "https://facebook.com/12345/posts/67890" },
    "x":        { "success": false, "error": "Upload rejected by the platform" }
  },
  "failed_platforms": ["x"]
}
```

Dùng một **Router** với bộ lọc theo `success` để chuyển các lỗi sang một cảnh báo.

## Ví dụ scenario: Google Sheets → mọi nền tảng

1. **Google Sheets → Watch rows** (hoặc *Search rows* theo lịch với `status = ready`).
2. **HTTP → Make a request** → `POST /v1/posts/photos` với `profile_id`, `platforms[]`, và `caption` map từ dòng đó; `Idempotency-Key` là một cột UUID trên dòng đó (không dùng số dòng, xem cảnh báo ở trên).
3. **Router** theo phản hồi → nếu thành công, **Google Sheets → Update a row** thành `published`; nếu lỗi, gửi cảnh báo.

## Bước tiếp theo

<CardGroup cols={2}>
  <Card title="Tuỳ chọn theo nền tảng" icon="sliders" href="/vi/concepts/posts">
    Ghi đè caption, tiêu đề và tuỳ chọn cho từng nền tảng.
  </Card>

  <Card title="Lên lịch" icon="calendar" href="/vi/concepts/scheduling">
    Để Hub tự đăng vào thời điểm tương lai.
  </Card>

  <Card title="Idempotency" icon="shield-check" href="/vi/concepts/idempotency">
    Chạy lại an toàn cho mọi quy trình tự động hóa.
  </Card>

  <Card title="Webhooks" icon="bolt" href="/vi/concepts/webhooks">
    Nhận callback có chữ ký khi bài đăng hoàn tất.
  </Card>
</CardGroup>
