ZyVOP Logo
Content That Connects
SeriesAI NewsLeaderboardWrite for Us
ZyVOP Logo
Content That Connects

Empowering developers and creators with cutting-edge insights, comprehensive tutorials, and innovative solutions for the digital future.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • API Documentation
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

© 2026 ZyVOP. Crafted with care for the developer community.

Made with ❤️ by the ZyVOP team
All systems operational
HomeTutorialWhat the Instagram API doesn't tell you about publishing
Tutorial

What the Instagram API doesn't tell you about publishing

chrononyte
chrononyteFounder, Chrononyte
August 10, 2026
4 min read
What the Instagram API doesn't tell you about publishing
#webdev#automation#api#instagram
👍1

I spent a while building a service that publishes to Instagram on a schedule. Most of that time did not go into the interesting parts. It went into errors whose message points nowhere near the actual cause.

Here is the list I wish I had found on day one.

1. Publishing is two calls, and the first one publishes nothing

You do not post a photo. You create a media container, then you publish that container:

POST /{ig-user-id}/media          -> returns a creation_id
POST /{ig-user-id}/media_publish  -> takes that creation_id

The first call is the one that looks like it worked. It returns an id, your workflow goes green, and nothing appears on the profile. That is not a silent failure: a container is a temporary object, and until you publish it, it is not a post.

If you are debugging "the API says OK but nothing is online", this is almost always it.

2. Instagram downloads the image itself, from a URL, with no cookies

For images you never upload bytes at all. You give Instagram an address, and Meta's servers go and fetch it. That single fact explains a whole family of errors, the most common being:

Only photo or video can be accepted as media type

which usually means: what came back from your URL was not an image. The classic case is a Google Drive share link. It looks like an image in your browser, but to a server with no session it answers with an HTML page, and Meta reads HTML, shrugs, and tells you it is not a photo.

So the address has to return the raw bytes with an image content type, publicly, no login. A quick check before you wire anything up:

curl -sIL "https://your-host/photo.jpg"

Look at the final status and the content type. If it is not 200 and image/jpeg or image/png, Instagram will not take it either. While you are there, avoid pointless redirects: an address that answers 301 and bounces elsewhere is one more thing that can go wrong in a hop you do not control.

3. Video is processed asynchronously, and nobody waits for you

Reels and video stories do not behave like images. After you create the container, Instagram has to process the file, and how long that takes depends on the video. Publish immediately and you get errors that read like something else entirely.

The container carries a status you are supposed to poll until it is finished. Meta's own docs, on the Threads side of the same family, put a number on the wait: "It is recommended to wait on average 30 seconds before publishing a media container to give our server enough time to fully process the upload."

If you are scheduling for a specific minute, this changes the shape of your job: you cannot start at that minute. You have to start before it, and publish when both the container is ready and the clock says go.

4. Carousels have edges that are easy to hit

Between 2 and 10 images. Images only. Each one has to be reachable at its own public address, and they can live on different hosts, which is handy when your slides come from different places.

The unpleasant part is when the check happens. If your own code accepts eleven images and passes them on, you find out at publish time, from Meta, hours after you queued the post. Every limit you know about is worth checking the moment the user asks for something, not when the job runs. I had this exact bug in my own service, and the fix was five lines.

5. The token that expires without telling anyone

Short-lived user tokens, long-lived user tokens, Page tokens. The one you want for publishing is a Page token, and the flow that gets you a permanent one is not the one you land on first. What happens otherwise is that everything works for a while and then quietly stops, usually on the day you are not looking.

Worth building the "your connection is no longer valid" path early, and making it loud. An automation that fails silently is worse than one that never worked, because you find out from the silence on your own profile.

6. What actually helped

Three habits, all boring:

  • Log what you sent, not just what came back. Half the 500s I chased were an expression that resolved to nothing, so the request went out with an empty parameter and Meta answered with something generic.

  • Read the media before sending it. Size, format, dimensions, duration. Knowing your own numbers turns "Meta rejected it" into "Meta rejected a 12 MB png", which is an answer.

  • Fail early, with the reason. Anything you can check when the post is queued should be checked there.


None of this is hard once you know it. It is just undocumented in the places you look first, and each item costs an afternoon.

I ended up turning all of it into a small service, Rubinyun, because I got tired of rebuilding the same queue: it holds the post, waits for the container, and publishes at the minute you asked for. But the list above is worth having whether or not you use anything of mine, and if you are building it yourself, the two-step flow and the video wait are the parts to get right first.

chrononyte

chrononyte

Founder, Chrononyte

Chrononyte started from a love for technology, the kind that keeps you up after work. The tools that come out of here always start from a real problem, the kind that costs you an evening, and they stay in the workshop until they hold up in someone else's hands.

Comments (0)

Login to post a comment.

Related Posts

How ZyVOP's Syndication Engine Works: Dev.to, Hashnode, Medium, and Bluesky

Cross-posting sounds simple until you try to build it. Every platform has different APIs, different formats, different quirks, and different failure modes. Here's the complete technical breakdown of how ZyVOP's syndication engine works under the hood.

Read article

The Real Cost of Running a Developer Platform

Most "cost of running my SaaS" posts hide the free tiers and skip the disasters. Here's every line item behind ZyVOP — including the Vercel timeout that was one slow API response away from silently killing cross-posts.

Read article

🚀 Excited to share one of my biggest full-stack learning projects so far — YouTube V2!

🚀 Excited to share one of my biggest full-stack learning projects so far — YouTube V2! Over the past few weeks, I've been building a modern YouTube-inspired pl...

Read article

🚀 Excited to share one of my biggest full-stack learning projects so far — YouTube V2!

🚀 Excited to share one of my biggest full-stack learning projects so far — YouTube V2! Over the past few weeks, I've been building a modern YouTube-inspired pl...

Read article

🚀 I Built a Full Stack Miro Clone with Real-Time Collaboration using Next.js

🚀 I Built a Full Stack Miro Clone with Real-Time Collaboration using Next.js After weeks of building, debugging, redesigning, and optimizing — I finally comple...

Read article