All questionsInstagram

Is there a webhook for new Instagram or TikTok posts?

No. Instagram and TikTok send webhooks only to apps that an account owner authorized, and only about that account. For a public account you do not own, nobody will call you. Openhandle does not offer webhooks either. It reads when you ask.

The working pattern is a poll. Read the profile posts endpoint on a schedule, compare post IDs with what you stored, and treat every new ID as an event. One page per check is enough, because the feed is newest first.

Checked September 2026 · request and response run against the API · no affiliate links

GET /v1/instagram/profiles/@username/posts?freshness=live
curl "https://api.openhandle.dev/v1/instagram/profiles/@northstar_forge_test/posts?freshness=live" \
  -H "Authorization: Bearer $OPENHANDLE_API_KEY"
TypeScript SDK
import { OpenHandle } from '@openhandle/sdk';

const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_API_KEY! });

// Run every 15 minutes. One page, newest first.
const page = await openhandle.instagram.profile('northstar_forge_test').posts.list({ freshness: 'live' });
for (const post of page.data) {
    if (await seen(post.id)) break;
    await onNewPost(post);
}
200 OK
{
  "platform": "instagram",
  "resource": "post",
  "capturedAt": "2026-09-18T11:45:00Z",
  "source": "live",
  "data": [
    {
      "id": "910100000001",
      "createdAt": "2026-08-09T15:30:00Z",
      "metrics": { "likes": 840, "comments": 5 }
    }
  ],
  "meta": { "cursors": { "next": "b3BhcXVlLWN1cnNvcg" } }
}

Trimmed to one post. Because the feed is newest first, you can stop at the first ID you already know. The example is a Test profile.

Pick a poll interval

You needIntervalCost per account per day
Same-dayEvery 6 hours4 live reads, $0.0025 each
Within the hourEvery 15 minutes96 live reads, $0.0025 each
A daily digestOnce a day1 read, $0.0005 on a cache hit or $0.0025 live

Use freshness=live for a poll. A cache hit could return the same page you saw last time. The TikTok profile posts endpoint works the same way with the same shape.

Make it robust

  • Key on `id`, not position. Pinned posts sit at the top of an Instagram feed. A new post can appear below them. Compare IDs, do not assume the first item is newest.
  • Store `capturedAt`. It is when the platform showed the post. Your event time should be that, not your cron time.
  • Handle a private flip. An account can go private between polls. PROFILE_PRIVATE is an event too. Store it and stop polling until you decide to retry.
  • Spread the schedule. A thousand accounts polled at the same minute hit your own rate limit. Stagger them across the interval.

When this does not work

These answers are events. Store them, do not retry them.

SituationStatusCode
The account went private403PROFILE_PRIVATE
The account is deleted or renamed without an ID lookup404PROFILE_NOT_FOUND
You passed your own per-second limit429RATE_LIMITED
429 Too Many Requests
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Retry after the Retry-After header.",
    "requestId": "req_01j8…",
    "retryable": true
  }
}

Rate limits are per key, 10 requests per second, and never billed. Honor Retry-After. Failed requests are never billed.

Read next

More Instagram questions

Send your agent ahead.

Paste the prompt into your agent and it sets everything up. Or come yourself, it takes five minutes.

For agents