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

> Publish to every platform from a Make (Integromat) scenario using the MADIAD Hub REST API.

Make talks to MADIAD Hub through its generic **HTTP → Make a request** module — no custom app to install. Add the module to any scenario and you can publish when a Google Sheet changes, on a schedule, from a form submission, or from anything else Make can trigger on.

<Note>
  This guide assumes you already have an API key and at least one connected profile. If not, do the [Quickstart](/quickstart) first (5 minutes).
</Note>

## 1. The building block: HTTP → Make a request

Every call below uses one module: **HTTP → Make a request**. The common settings:

| Field          | Value                                                    |
| -------------- | -------------------------------------------------------- |
| URL            | `https://api.madiad.com/v1/…` (endpoint per media type)  |
| Method         | `POST`                                                   |
| Headers        | `Authorization: Bearer mdc_live_…`                       |
| Parse response | **Yes** — so the JSON reply is mapped into later modules |

<Warning>
  Create a **separate API key** for Make (name it `make` in your dashboard). If it leaks, revoke that one key without touching your other integrations. Store it in a scenario variable or Make's data store rather than pasting it into every module.
</Warning>

## 2. Publish a text post

Add **HTTP → Make a request**:

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

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "platforms": ["facebook", "linkedin", "x"],
  "caption": "New article is live — read it on the blog."
}
```

Text posts use JSON. **Photos and video use different formats** — see [Publishing files](#4-publish-photos-or-video) below.

## 3. Make retries safe with an Idempotency-Key

Make re-runs a module on error or when you replay a scenario. To avoid a duplicate post, add a header whose value is stable per item — the Hub treats a repeat of the same key as the same request.

Add a header:

| Name              | Value                                                                                                           |
| ----------------- | --------------------------------------------------------------------------------------------------------------- |
| `Idempotency-Key` | map a field that is unique per post and never recycled — a UUID column or a record ID, **not** the `Row number` |

Use a value that is **unique per intended post** and **constant across retries of that same post**. Good choices: a UUID you generate once and write back to the row, or a hash of the content itself.

<Warning>
  **Never use a value that gets reused.** A spreadsheet row number shifts when rows are deleted, so tomorrow's content ends up carrying a key that yesterday's post already claimed. The Hub answers a reused key with the ORIGINAL result and publishes nothing, so a broken key looks exactly like a successful post. Watch for the `Idempotent-Replayed: true` header, and see [Idempotency](/concepts/idempotency).
</Warning>

## 4. Publish photos or video

**Photos** — `POST /v1/posts/photos`. Set **Body type** to `Multipart/form-data`, repeat `platforms[]` once per platform, and attach the image through a **file** field mapped from a previous module (e.g. *Google Drive → Download a file*, or *HTTP → Get a file*):

| Field name    | Type | Value                                             |
| ------------- | ---- | ------------------------------------------------- |
| `profile_id`  | Text | `prof_…`                                          |
| `platforms[]` | Text | `instagram`                                       |
| `platforms[]` | Text | `facebook`                                        |
| `caption`     | Text | `New blend dropping today`                        |
| `photos[]`    | File | the `data` + `file name` from the download module |

Already have a public image URL instead of a file? Skip the upload and send `photo_urls[]` as **Raw JSON** instead — see [Send photos by URL](/concepts/posts#send-photos-by-url).

**Video** — `POST /v1/posts/video` takes JSON only, not a file upload. Set **Body type** to `Raw` / `application/json` and pass a public `video_url`:

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

## 5. Handle the async response

A text or photo post to fast platforms usually returns `"status": "completed"`. **Video is asynchronous** — it returns `"status": "processing"` and a `request_id`. Two ways to finish:

**Poll** — add a **Sleep** module, then another **HTTP → Make a request**:

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

Wrap it in a **Repeater** and stop when `status` is `completed`, `partial`, or `failed`.

**Webhook (recommended)** — add a **Custom webhook** module in Make, copy its address, and register it in your dashboard at [hub.madiad.com/dashboard/webhooks](https://hub.madiad.com/dashboard/webhooks) for the `post.completed` event. The Hub signs each delivery with HMAC-SHA256; verify it before trusting the payload. See [Webhooks](/concepts/webhooks).

## 6. Read per-platform results

With **Parse response** on, map the reply directly. A post can partially succeed — branch on each platform's `success`, not just the top-level `status`:

```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"]
}
```

Use a **Router** with a filter on `success` to send failures to an alert.

## Example scenario: Google Sheets → all platforms

1. **Google Sheets → Watch rows** (or a scheduled *Search rows* where `status = ready`).
2. **HTTP → Make a request** → `POST /v1/posts/photos` with `profile_id`, `platforms[]`, and `caption` mapped from the row; `Idempotency-Key` = a UUID column on the row (not the row number — see the warning above).
3. **Router** on the response → on success, **Google Sheets → Update a row** to `published`; on failure, send an alert.

## Next steps

<CardGroup cols={2}>
  <Card title="Per-platform fields" icon="sliders" href="/concepts/posts">
    Override captions, titles, and options per platform.
  </Card>

  <Card title="Scheduling" icon="calendar" href="/concepts/scheduling">
    Let the Hub publish at a future time for you.
  </Card>

  <Card title="Idempotency" icon="shield-check" href="/concepts/idempotency">
    Safe retries from any automation.
  </Card>

  <Card title="Webhooks" icon="bolt" href="/concepts/webhooks">
    Get a signed callback when a post finishes.
  </Card>
</CardGroup>
