API Reference
GET /feeds/{username} returns your Instagram posts as a JSON array. Responses are cached at the edge, authenticated with a public-key query parameter, and work in any framework.
A single GET endpoint serves the cached feed for a connected Instagram account. The endpoint is CORS-open and authenticates with a public-key query parameter. Below is the full surface.
Endpoint
GET https://www.feed-fusion.com/api/feeds/{username}?publicKey={publicKey}The username path segment is your Instagram handle (the same one shown on the feed page in your dashboard). The publicKey query parameter is a 32-character hex string from the same dashboard page. Both must match a single connected feed; mismatched pairs return 403.
Query parameters
| Prop | Type | Default | Description |
|---|---|---|---|
publicKey | string | required | 32-character hex from your dashboard. Tied to the username path segment. |
limit | number (1 to 100) | 24 | Posts to return in this response. Out-of-range values clamp to the bounds. |
offset | number (0 or greater) | 0 | Starting index of the slice. Use with limit for pagination. |
Example response
{
"username": "your-instagram-handle",
"meta": {
"tier": "free",
"total": 28,
"limit": 12,
"offset": 0,
"cacheTtl": 3600
},
"posts": [
{
"id": "18418647295121497",
"timestamp": "2026-04-02T09:49:14+0000",
"permalink": "https://www.instagram.com/p/DWn_VzyDB65/",
"mediaType": "IMAGE",
"mediaUrl": "https://scontent-iad3-1.cdninstagram.com/...",
"thumbnailUrl": null,
"caption": "..."
}
]
}Response fields
Top-level:
| Prop | Type | Default | Description |
|---|---|---|---|
username | string | required | Echoes the username from the URL. Useful for logging. |
meta | object | required | Pagination + tier + cache info (see below). |
posts | Post[] | required | Array of post objects (see below). May be empty if the account has no posts yet. |
meta object:
| Prop | Type | Default | Description |
|---|---|---|---|
tier | "free" | "pro" | "agency" | required | The subscription tier of the feed's owner. Use it to drive tier-aware client behaviour if needed. |
total | number | required | Total posts available in the cached feed, before applying limit/offset. Use to detect when pagination ends. |
limit | number | required | Posts actually returned in this response. Matches the limit query param after clamping. |
offset | number | required | Starting index of this slice. Matches the offset query param. |
cacheTtl | number | required | Edge cache TTL in seconds (3600 at time of writing). Match your client-side cache to this for the most efficient setup. |
post object:
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | required | Instagram post ID. Stable; use as React key. |
timestamp | string | required | ISO 8601 timestamp from Instagram (e.g. "2026-04-02T09:49:14+0000"). |
permalink | string | required | Public Instagram URL for the post. Link to this on click. |
mediaType | "IMAGE" | "VIDEO" | "CAROUSEL_ALBUM" | required | Type of post. |
mediaUrl | string | required | Direct URL to the media file. For VIDEO posts, this is the video file; for IMAGE posts, the image. |
thumbnailUrl | string | null | required | Cover image for VIDEO and CAROUSEL_ALBUM. null for plain IMAGE posts (use mediaUrl directly). |
caption | string | null | required | Post caption. Can be null for posts without text. |
Response headers
| Prop | Type | Default | Description |
|---|---|---|---|
X-Ratelimit-Limit | number | required | Per-minute rate limit cap for this publicKey (600 at time of writing). |
X-Ratelimit-Remaining | number | required | Requests remaining in the current sliding-window minute. |
X-Ratelimit-Reset | number | required | Unix timestamp (seconds) when the rate limit window resets. |
Retry-After | number | — | Seconds to wait before retrying. Only present on 429 responses. |
Access-Control-Allow-Origin | string | required | Always *. CORS-open for browser-side widgets. |
Access-Control-Expose-Headers | string | required | Exposes the four X-Ratelimit-* and Retry-After headers to browser JavaScript. |
Status codes
| Prop | Type | Default | Description |
|---|---|---|---|
200 | OK | required | Returns the feed JSON. Rate-limit headers populated. |
400 | Bad Request | required | Missing username or publicKey query parameter. |
403 | Forbidden | required | Username and publicKey don't match a connected feed. Returned without consuming rate-limit quota; invalid pairs are typically bots. |
429 | Too Many Requests | required | Either the per-minute rate limit (600/min by publicKey) or the monthly plan view limit was exceeded. Retry-After header tells you when to retry. |
500 | Internal Server Error | required | Database error or other upstream failure. Captured in our error monitoring; retry with backoff. |
Rate limits
The endpoint allows up to 600 requests per minute per publicKey, on a sliding window. That's more than enough for any normal site traffic; we built it to absorb traffic spikes without throttling the legitimate visitors.
Monthly view caps apply on top of per-minute rate limits:
| Prop | Type | Default | Description |
|---|---|---|---|
Free | tier | required | 10,000 widget views per month, 10 manual refreshes per month. |
Pro | tier | required | 100,000 widget views per month, 100 manual refreshes per month. |
Agency | tier | required | Unlimited views, unlimited manual refreshes. |
Caching and CORS
Responses are cached at the edge for one hour (see meta.cacheTtl). The endpoint is fully CORS-open for browser embeds; you can call it from client-side JavaScript, server-side Node, mobile apps, anywhere.
Questions? hello@feed-fusion.com
Continue reading