# Publish to Instagram with the API
URL: https://skedcast.com/developers/guides/publish-to-instagram-api

Instagram uses the same POST /v1/posts call as every other platform. A single video with no contentType publishes as a Reel. Everything else (feed, Story, tags, collaborators) is an explicit override.

## What do you need before you publish?
You need one connected account for the platform. Connect it in the SkedCast console. If a client owns the account, create a connect link with `POST /v1/clients/{id}/connect-invites` and send it to them. They authorize from that page without a SkedCast login.
`GET /v1/accounts` lists the connected accounts with their ids. Pass that id in `targets.accountIds` below.

## How do you schedule a Instagram post with the API?
```bash
curl -X POST https://api.skedcast.com/v1/posts \
  -H "Authorization: Bearer sked_live_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "<clientId>",
    "content": "Launch day is here 🚀",
    "mediaIds": ["<mediaAssetId>"],
    "targets": { "mode": "selection", "accountIds": ["<instagramAccountId>"] },
    "schedule": { "type": "at", "scheduledAt": "2030-01-15T15:00:00Z" }
  }'
```

## Which Instagram fields can you set?
Put everything platform-specific in one `variants` entry with `"platform": "instagram"` and an `overrides` object. Send only `instagram` keys on a `instagram` variant. SkedCast reads the keys in the table below and ignores the rest.

## Reference
Field | Type | Values / default | Notes
`contentType` | enum | `feed` \| `reel` \| `story` | Defaults to `feed`. A single video with no `contentType` publishes as a Reel.
`firstComment` | string | — | Posted right after publish. Needs the account's `instagram_manage_comments` permission. Without it the comment is held back at publish and `firstCommentIssue` says so. Best-effort: a failed comment never fails the post. The outcome is reported as `firstCommentIssue` on `GET /v1/post-targets/{id}`.
`commentsEnabled` | boolean (or `"true"` / `"false"`) | `true` | `false` turns comments off as soon as the post is live (live media only, not Stories). Needs the same `instagram_manage_comments` permission as the first comment.
`userTags` | string[] or `[{ username, x?, y? }]` | ≤20 | People and photo tags. A comma-separated string of `@usernames` also works.
`collaborators` | string[] | ≤3 | Collaborator usernames.
`shareToFeed` | boolean | platform default | Reels only: also show the Reel in the main feed grid.
`coverUrl` | string (url) | — | Reels only: a public URL for the Reel's cover frame. Separate from the post-level `coverMediaId`.
`locationId` | string | — | Instagram location page id.
`paidPartnership` | boolean | `false` | Adds Instagram's "Paid partnership" disclosure label.

## Unknown keys are ignored without an error
A misspelled or unknown key in `overrides` is not an error and not a warning. It is dropped, so check the field names in the table above, especially a required one.
A YouTube-only key (such as `privacyStatus`, `captions` or `chapters`) sent on another platform's variant is ignored and returns an `override_key_wrong_platform` warning.

## How do you add Instagram-specific settings?
```json
{
  "clientId": "<clientId>",
  "content": "Behind the scenes 🎬",
  "mediaIds": ["<videoAssetId>"],
  "targets": { "mode": "selection", "accountIds": ["<instagramAccountId>"] },
  "variants": [
    {
      "platform": "instagram",
      "overrides": { "contentType": "reel", "shareToFeed": true, "collaborators": ["studio_handle"] }
    }
  ],
  "schedule": { "type": "at", "scheduledAt": "2030-01-15T15:00:00Z" }
}
```

## How do you check that the post published?
Publishing creates one post target per account. `GET /v1/post-targets/{id}` (or `GET /v1/posts/{id}`) reports `status`, plus `externalId` (Instagram's own post id) and `permalink` (its public URL) once published. To avoid polling, subscribe to the `target.published` and `target.failed` webhooks (see the webhooks guide).

## FAQ
**Q: Will my video publish as a Reel or a feed post?**
A: A single video with no contentType publishes as a Reel. Set contentType: "feed" to publish it as a regular video post in the grid instead.

**Q: Can I post an Instagram carousel?**
A: Yes. Pass more than one id in the base mediaIds array (no contentType override needed) and SkedCast publishes a carousel. Set per-slide alt text with the post-level mediaAltTexts map, keyed by media asset id.
