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

# Refresh, then automate the post you just published

> Your publishing tool posts a reel. Seconds later, it's answering comments.

The first hour after a post goes up is when the comments come. This recipe puts an automation on a reel the moment your publishing tool posts it, so the earliest comments get their DM too.

inDM pulls posts from Instagram on a schedule, so a reel published a minute ago usually isn't in [List media](https://docs.indm.social/api-reference/media/list-media.md) yet. The flow is: look for it, refresh if it's missing, wait for the refresh, then build and launch.

You need a `full` key and the reel's permalink, which your publishing tool gets back from Instagram when it posts.

**1. Look for the post**

List the account's newest media and match on `permalink`. If it's there, skip to building the automation.

**2. Refresh if it's missing**

[Refresh content](https://docs.indm.social/api-reference/accounts/refresh-account.md) asks Instagram for the newest posts. It returns `202` with a `job_id` to poll, or `200` with `status: "already_current"` when the account synced within the last minute.

**3. Wait for the refresh**

Poll [Get a refresh](https://docs.indm.social/api-reference/accounts/get-refresh.md) every few seconds until `status` is `completed`, then look again. If the account answered `already_current` and the post still isn't there, Instagram may not be serving it yet: wait a minute and refresh once more.

**4. Build it and set it live**

[Create the automation](https://docs.indm.social/api-reference/automations/create-automation.md) as a draft, then [set it live](https://docs.indm.social/api-reference/automations/set-automation-status.md).

## The whole flow

```javascript Node theme={null}
const API = "https://api.indm.social/v1";
const headers = {
  Authorization: `Bearer ${process.env.INDM_API_KEY}`,
  "Content-Type": "application/json",
};
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function call(method, path, body) {
  const res = await fetch(API + path, {
    method,
    headers,
    body: body ? JSON.stringify(body) : undefined,
  });
  const json = await res.json();
  if (!res.ok) throw new Error(`${json.error.code}: ${json.error.message}`);
  return { status: res.status, json };
}

async function findPost(accountId, permalink) {
  const { json } = await call("GET", `/media?account_id=${accountId}&limit=10`);
  return json.data.find((m) => m.permalink === permalink);
}

async function refreshAndWait(accountId) {
  const { status, json } = await call("POST", `/accounts/${accountId}/refresh`);
  if (status === 200) return json.status; // "already_current"
  for (let i = 0; i < 60; i++) {
    await sleep(3000);
    const job = await call("GET", `/accounts/${accountId}/refresh/${json.job_id}`);
    if (!["pending", "running"].includes(job.json.status)) return job.json.status;
  }
  return "running";
}

export async function automateNewPost({ accountId, permalink }) {
  let post = await findPost(accountId, permalink);

  for (let attempt = 0; !post && attempt < 3; attempt++) {
    const outcome = await refreshAndWait(accountId);
    if (outcome === "already_current") await sleep(60_000);
    post = await findPost(accountId, permalink);
  }
  if (!post) throw new Error("The post hasn't reached inDM yet. Try again shortly.");

  const { json: automation } = await call("POST", "/automations", {
    media_id: post.id,
    keywords: ["GUIDE"],
    public_reply: "Sent it to your DMs.",
    dm_message: "Here is the spring planting guide. Enjoy it.",
    button_label: "Send me the guide",
    link_url: "https://example.com/spring-guide",
  });

  await call("POST", `/automations/${automation.id}/status`, { status: "live" });
  return automation.id;
}
```

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

API = "https://api.indm.social/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['INDM_API_KEY']}"}


def call(method, path, body=None, params=None):
    res = requests.request(method, API + path, headers=HEADERS, json=body, params=params)
    data = res.json()
    if not res.ok:
        raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
    return res.status_code, data


def find_post(account_id, permalink):
    _, page = call("GET", "/media", params={"account_id": account_id, "limit": 10})
    return next((m for m in page["data"] if m["permalink"] == permalink), None)


def refresh_and_wait(account_id):
    status, job = call("POST", f"/accounts/{account_id}/refresh")
    if status == 200:
        return job["status"]  # "already_current"
    for _ in range(60):
        time.sleep(3)
        _, job = call("GET", f"/accounts/{account_id}/refresh/{job['job_id']}")
        if job["status"] not in ("pending", "running"):
            return job["status"]
    return "running"


def automate_new_post(account_id, permalink):
    post = find_post(account_id, permalink)

    attempt = 0
    while post is None and attempt < 3:
        if refresh_and_wait(account_id) == "already_current":
            time.sleep(60)
        post = find_post(account_id, permalink)
        attempt += 1
    if post is None:
        raise RuntimeError("The post hasn't reached inDM yet. Try again shortly.")

    _, automation = call("POST", "/automations", {
        "media_id": post["id"],
        "keywords": ["GUIDE"],
        "public_reply": "Sent it to your DMs.",
        "dm_message": "Here is the spring planting guide. Enjoy it.",
        "button_label": "Send me the guide",
        "link_url": "https://example.com/spring-guide",
    })

    call("POST", f"/automations/{automation['id']}/status", {"status": "live"})
    return automation["id"]
```

## Good to know

* **One live automation per post.** If something is already live on the reel, creating returns [`409 live_automation_on_media`](https://docs.indm.social/errors#live_automation_on_media). Pause the other one first, or let it be.
* **A paused account can't refresh.** If Instagram has paused the connection, refresh returns [`409 account_needs_reconnect`](https://docs.indm.social/errors#account_needs_reconnect). [Get account health](https://docs.indm.social/api-reference/accounts/get-account-health.md) says why.
* **A first sync takes longer.** If the account was connected moments ago, refresh answers `status: "backfill"` and hands you its first full sync to poll. Large accounts take a few minutes.
* **Validate the copy first** if it comes from somewhere you don't control. [Validate an automation](https://docs.indm.social/api-reference/automations/validate-automation.md) catches a label Instagram would cut off before anything is saved.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.