- You can filter imports by surface and media type.
- You can request richer media metadata in
extraData(when platform returns direct media URLs). extraDatais now normalized asextraData.media[].- For platforms/endpoints that do not expose direct media URLs (e.g. current YouTube import path),
extraDataisnull.
How it works
This is an asynchronous job. You don’t get the posts instantly.- Start: You trigger a job (“Go fetch 50 posts from Instagram”).
- Wait: We queue it, talk to the platform, and crunch the data.
- Poll: You check if we’re done.
- Fetch: You download the results.
Step 1: Start the Job
Endpoint:POST /api/v1/post-history-import
Import filters and media options
surfacelets you choose where the content comes from (ALL,PROFILE_GRID,NON_GRID,STORY).mediaTypefilters by content type (VIDEOorIMAGE).importCarouselscontrols whether carousel child media is expanded intoextraData.media[]when supported.
Platform APIs are inconsistent. Some filters/surfaces may return no data on specific platforms if that API does not expose that view.
- Free: 5 posts / month (Demo mode)
- Pro: 100 posts / month
- Business: 250 posts / month
Why limits? Historical imports are expensive on API tokens. We have to be stingy here to keep the service cheap for everyone.
Imported post analytics
By default, imported posts get an initial analytics snapshot at import time whenwithAnalytics: true.
Ongoing Analytics Refresh
Imported posts can also be added to the regular analytics refresh cycle - meaning they get updated on the same schedule as posts created through bundle.social. This is controlled by an organization-level setting. When enabled:- Imported posts are included in the regular analytics scanner.
- You can fetch analytics for imported posts via the standard analytics endpoints using
importedPostIdinstead ofpostId. - You can force-refresh analytics for imported posts the same way you would for regular posts.
importedPostId vs postId: When querying analytics for imported posts, use importedPostId (the imported post’s ID). Don’t mix it with postId + platformType - they’re mutually exclusive.Step 2: Check Status
Endpoint:GET /api/v1/post-history-import?teamId=...
You’ll see a list of jobs with statuses:
PENDING: In queue.FETCHING_POSTS: Talking to Instagram…COMPLETED: Done!FAILED: Something exploded.RATE_LIMITED: Platform said “slow down”. We paused it for you.
Step 3: Get the Loot
Endpoint:GET /api/v1/post-history-import/posts
Once status is COMPLETED, call this to get the actual data.
extraData structure
When available, imported posts include:
extraData is null.
Current YouTube history import returns
extraData: null.Handling Rate Limits
If a job hitsRATE_LIMITED, don’t panic. It means we hit the platform’s cap (e.g. LinkedIn API limits).
- We automatically pause the job.
- We set a
rateLimitResetAttimestamp. - You can retry it after that time.