> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs-parschat.parstechai.com/documentation/guides/rate-limits/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-parschat.parstechai.com/_mcp/server. # Rate limits > Instagram's limits are the ones that bind. We do not add a per-plan cap of our own, and replies we cannot send immediately are queued rather than dropped. > **Warning** > > **Pre-release `v1`, published 2026-09-14.** This page commits to the shape of the API, not to a > date. We will build exactly what is documented here. The shape can still change until > **2026-10-14**; after that, changes follow [Versioning and stability](/documentation/reference/versioning-stability). > > The banner comes off one page at a time as each route goes live. While it is here, build against > the contract and assume the route is not callable yet. Two different things are limited here, and they behave in opposite ways. | | Limit | What happens when you reach it | | -------------------------------- | ---------------------------------- | ---------------------------------------- | | **Calls you make to us** | **300 per minute**, from your plan | `429`. You retry | | **Replies we send to Instagram** | Instagram's own, per account | **Queued and sent later.** Never dropped | Get that distinction right and the rest of this page follows: `429` always means *you are calling us too fast*, and it never means a reply to your customer was thrown away. ## Your call limit **300 requests per minute** by default, counted per account rather than per API key, so extra keys do not buy extra throughput. It is a **plan dimension**. If your integration genuinely needs more, it is raised for your account rather than by changing a shared number — ask your account manager. The window **slides**: we count the last 60 seconds continuously rather than resetting on a clock minute, so you cannot spend one minute's allowance at the end of one window and the next at the start of the following. When you exceed it: ```json { "error": { "code": "rate_limited", "message": "API rate limit exceeded. Slow down and retry shortly.", "request_id": "req_8f2Kq9mR", "details": { "limit_per_minute": 300, "window_seconds": 60 } } } ``` `details` names the number you are held to, so you can tell a raised limit from the default without asking us. > **Info** > > **300/min is sized against real traffic, not guessed.** A partner with 500 pages generates about > **7 requests a minute** at peak from replies. What actually consumes an allowance is polling — > 500 pages polled once a minute is 500 requests a minute on its own. If you are near this limit, > you are almost certainly polling something that should be a > [webhook](/documentation/guides/webhook-events). > **Note** > > A blunt per-IP ceiling also sits at our gateway as infrastructure protection. It is set far above > every account limit, so you will meet the limit above — which names its number and can be > raised — rather than an opaque gateway rejection. It is not a product dimension and is not sold. ## Instagram's limits Enforced **per Instagram account**, not per app, per key or per plan. No ParsChat plan raises them. | Operation | Limit | Hourly equivalent | | --------------------------------------------- | -------------- | ----------------: | | Send text, links, reactions, stickers | 100 / second | 360,000 | | Send audio or video | 10 / second | 36,000 | | Read conversations | 2 / second | 7,200 | | Private reply — comment on a **post or reel** | **750 / hour** | **750** | | Private reply — comment on a **Live** | 100 / second | 360,000 | Messaging is counted **separately** from the impressions budget below, so sending a DM does not draw down the quota that reading comments uses. ### 750 per hour is the one that binds A **private reply** is a DM triggered by someone's comment — the core of comment-to-DM automation. On comments under a **post or reel** you get 750 per hour, which is roughly one every five seconds sustained and does not grow with the account's size. > **Info** > > This ceiling is reached by **success**, not by misuse. One post doing unusually well exhausts it, > and no plan raises it. **Comments on a Live stream are different: 100 per second, a 480× higher ceiling.** If you are building for Live selling, do not plan against 750 — it does not apply to you. Live commerce is a common pattern on Instagram, and the two limits are far enough apart that assuming the stricter one would make you queue traffic you could have sent immediately. The send ceilings (100/s, 10/s) are orders of magnitude above anything this product generates. They are listed for completeness; you will not design around them. ## The impressions budget Everything that is **not** messaging — reading comments, replying publicly, hiding, listing posts — shares one 24-hour budget: ``` calls per 24h = 4,800 × impressions in the last 24h ``` The consequence is counter-intuitive and worth stating plainly: **a busy account has effectively unlimited quota, and a quiet one has almost none.** | Impressions in 24h | Calls available | | -----------------: | --------------: | | 10,000 | 48,000,000 | | 1,000 | 4,800,000 | | 100 | 480,000 | | 10 | 48,000 | | 0 | 0 | That is usually fine, because work scales with reach: a page nobody sees receives no comments to answer. **Polling is the exception**, because it scales with time instead. | | Calls per day | | ------------------------------------- | -----------------------------: | | Polling for comments every 30 seconds | 2,880, even with zero comments | | Webhook, answering 200 comments | 200 | On a page with one impression a day the whole budget is 4,800, and polling alone burns 60% of it achieving nothing. > **Warning** > > **Do not poll for new messages or comments.** Use [webhook events](/documentation/guides/webhook-events). > A webhook delivery costs nothing against this budget, and on a small account polling can exhaust > your customer's entire daily quota on its own. ## The 24-hour reply window **You have 24 hours to reply to an end user's message.** After that Instagram refuses the reply, whatever your automation rules say. This is the one that bites hardest, because it is not a slowdown. A reply sent at 25 hours does not arrive late — it does not arrive. | | | | ---------------- | --------------------------------------------------------- | | Clock starts | The end user's last message | | Applies to | Every reply, automated or from an operator | | After it expires | The send fails. There is no queue and no retry that helps | Show your operators how long is left on a conversation rather than letting them discover the window by failing to answer. ## Message history stops at 20 Instagram returns only the **20 most recent messages** in a conversation. Older ones are not paginated — they are unreachable. This is why webhook delivery matters more than it looks: if your endpoint is down, you cannot backfill what you missed beyond those 20 messages. **A webhook outage is not repairable after the fact.** Treat delivery failures as something to alert on, not something to reconcile later. ## Replies are queued, not dropped When a reply cannot be sent immediately — because Instagram refused it, or because our own send queue is draining — it is **held and sent later**. Nothing is discarded. | | If we dropped | What we actually do | | --------------------- | ---------------------------------------------- | ------------------------------ | | Your obligation | Detect the drop, re-send, build your own queue | **None**. We hold it | | End user's experience | No reply at all | A later reply | | Your customer | Silently loses conversations | Sees slower replies under load | **Why queue rather than reject:** the requests being held are *automated replies to a real person who messaged a shop*. Dropping one costs a customer conversation, and you could not meaningfully retry it anyway. By the time you noticed, the moment has passed. ### The queue holds for two hours A queued reply is held for at most **2 hours**. After that it is dropped and recorded. A reply is only worth sending while the person is still in the conversation. Past a couple of hours the end user has moved on. An answer arriving then reaches someone who has forgotten the question, and makes your product look erratic rather than slow. Two hours also bounds the backlog itself: the queue is limited by time rather than by a separate depth limit. ### What you see | | | | ------------------------------ | -------------------------------------------------------------------------------------- | | **Your own API calls** | `429 rate_limited`, naming your limit in `details`. You *can* meaningfully retry these | | **Outbound automated replies** | Never rejected. Queued and sent when capacity frees | So `429` always means *"you are calling us too fast"*. It never means *"your customer's reply was thrown away."* > **Note** > > We do not pass Instagram's own rate-limit state through this API. If a call fails because > Instagram refused it rather than because we did, you will see it as a failed send rather than a > `429`. ## Files, voice and documents Attachment size **is** a plan dimension. Limits are per file, checked at upload. | Kind | Basic | Professional | Accepted types | | ----------------- | ----: | -----------: | ---------------------------------------------------------------------------------------------- | | **Image** | 2 MB | **4 MB** | `image/jpeg` · `image/png` | | **Video** | 10 MB | **20 MB** | `video/mp4` · `video/quicktime` (.mov) · `video/webm` · `video/ogg` · `video/x-msvideo` (.avi) | | **Voice / audio** | 5 MB | **10 MB** | `audio/aac` · `audio/mp4` · `audio/x-m4a` · `audio/wav` | | **Document** | 5 MB | **10 MB** | `application/pdf` | The usual alternative spellings are accepted too (`image/jpg`, `video/avi`, `audio/m4a`, `audio/wave`, `audio/x-wav`, `audio/vnd.wave`). This is exactly what Instagram delivers: **GIF, WebP and other formats are refused at upload**, rather than accepted and then failing when you send. Every plan with API access sends all four types — the difference between tiers is size, not which kinds of file you may send. If your agreement sets different caps, those apply instead of the table above. > **Info** > > These are **our** limits, not Instagram's. Instagram allows considerably more (8 MB images, 25 MB > for everything else). We set lower caps deliberately: adopting Instagram's ceilings would more > than double steady-state storage for a capability almost nobody uses. ### What counts | | | | ----------------------------- | ---------------------------------------------------------------------------- | | Per **file**, not per message | A message with three images is checked three times | | Checked at **upload** | `POST /attachments` fails, not the later send | | Outside the allowlist | `422 validation_failed`, before anything is stored | | Over your plan's cap | `422 validation_failed`, with `kind`, `cap_mb` and `size_bytes` in `details` | | A kind your plan excludes | `403 attachment_not_in_plan` | > **Info** > > A voice note is an ordinary attachment with `type: voice`, so the audio limit applies. At 64 kbps > — a normal voice-note bitrate — **5 MB is about 10 minutes** and **10 MB about 21 minutes**, so > size is rarely the constraint in practice. ### Unsent uploads expire after 24 hours An attachment you upload but never send is discarded after **24 hours**. Upload close to when you send. The two-step flow exists so a large upload can be retried without re-sending the message — not so you can stage files in advance. ## How long conversations are kept Conversation history is retained for a period that comes from the plan, then removed. | Plan | Instagram plans | Standard plans | | ---------------- | --------------- | -------------- | | **Basic** | 6 months | 6 months | | **Business** | — | 1 year | | **Professional** | 1 year | 1 year | > **Note** > > If an account holds more than one subscription, **the longest retention wins.** Retention is a > duration, not a quota: adding a 6-month and a 1-year plan to get 18 months would be meaningless, > and taking the shorter would delete history a customer paid a higher tier to keep. Retention runs whether or not a channel is still enabled, so disabling a channel preserves its configuration and rules but does **not** freeze the clock on its conversations. Export anything you need to keep beyond your window. ## What to build for | Limit | Who absorbs it | What you must do | | ---------------------------------------------------------- | ------------------------ | --------------------------------------- | | **Your** 300 calls / minute | Retry on `429` | Back off, and stop polling | | Gateway per-IP ceiling | Set far above your limit | Nothing. You meet yours first | | Instagram **750 private replies / hour** (posts and reels) | Our queue holds them | Expect delay on a viral post | | Instagram **Live** private replies (100 / s) | — | Nothing. Do not plan against 750 here | | Instagram **24-hour window** | Nobody | Reply inside the window | | Instagram **impressions budget** | Avoidable | Use webhooks, never poll | | Instagram **20-message history** | Nobody | Keep your webhook endpoint healthy | | Attachment size | — | Check your plan's caps before uploading | > Instagram's limits are the ones that bind. We do not add a per-plan cap of our own, and replies we cannot send immediately are queued rather than dropped.