Postato Docs
GuidesCookbook

Instagram carousel

Multi-photo post with user tags and per-photo alt text.

Instagram carousel

A carousel is 2–10 images (or videos) shown as a swipeable unit. On Postato, you build it as a single content item with multiple media attachments.

Shape

{
  "platform": "instagram",
  "accountId": "acc_01H...",
  "status": "publish",
  "postType": "carousel",
  "content": [
    {
      "text": "Launch day, in photos.",
      "media": [
        { "id": "med_01H...photo1", "alt": "Team cheering at release moment" },
        { "id": "med_01H...photo2", "alt": "Dashboard metrics hitting target" },
        { "id": "med_01H...photo3", "alt": "Office whiteboard with launch plan" }
      ]
    }
  ]
}

Auto-promotion

If you send postType: "feed" with 2+ media items in a single content item, Postato automatically upgrades to carousel. You don't have to classify upfront; just attach the media and we match it to the right Instagram format.

User tagging

Tag people by handle + position on the photo. Coordinates are normalized 0–1 (top-left is 0, 0):

{
  "id": "med_01H...photo1",
  "alt": "Team cheering",
  "userTags": [
    { "username": "teammate_one", "x": 0.3, "y": 0.4 },
    { "username": "teammate_two", "x": 0.7, "y": 0.35 }
  ]
}

User tags are Instagram-only and work only on images (not videos). Tagging a username that doesn't exist silently fails at publish; Instagram just omits the tag.

Full call

// 1. Upload each photo via presigned URLs (see Media upload guide)
const photos = await Promise.all([
  uploadMedia('./photo1.jpg', 'image/jpeg'),
  uploadMedia('./photo2.jpg', 'image/jpeg'),
  uploadMedia('./photo3.jpg', 'image/jpeg'),
]);

// 2. Compose and publish
const response = await fetch(
  `https://api.postato.com.br/v1/workspaces/${WORKSPACE_ID}/posts`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': crypto.randomUUID(),
    },
    body: JSON.stringify({
      platform: 'instagram',
      accountId: INSTAGRAM_ACCOUNT_ID,
      status: 'publish',
      postType: 'carousel',
      content: [
        {
          text: 'Launch day, in photos.',
          media: photos.map((id, i) => ({
            id,
            alt: `Launch photo ${i + 1}`,
          })),
        },
      ],
    }),
  }
);
import uuid
import httpx

# 1. Upload each photo via presigned URLs (see Media upload guide)
photos = [
    upload_media("photo1.jpg", "image/jpeg"),
    upload_media("photo2.jpg", "image/jpeg"),
    upload_media("photo3.jpg", "image/jpeg"),
]

# 2. Compose and publish
response = httpx.post(
    f"https://api.postato.com.br/v1/workspaces/{WORKSPACE_ID}/posts",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "platform": "instagram",
        "accountId": INSTAGRAM_ACCOUNT_ID,
        "status": "publish",
        "postType": "carousel",
        "content": [
            {
                "text": "Launch day, in photos.",
                "media": [
                    {"id": mid, "alt": f"Launch photo {i + 1}"}
                    for i, mid in enumerate(photos)
                ],
            },
        ],
    },
    timeout=60,
)

Constraints

  • 2–10 media items per carousel. Fewer → Postato sends a regular feed post. More → Instagram rejects.
  • Mixed images + videos is allowed. Each slide is independent.
  • Caption (the text) applies to the whole carousel, not per-slide. Captions above 2,200 characters fail.
  • Location tagging and collaborator mentions go in options; see the API reference for exact shape.

A reel is always a single video, not a carousel. If you need a reel, use postType: "reel" with one video attachment. Postato does not transcode between formats; use the right postType upfront.

On this page