A feed represents a set of the most recent Instagram posts published to an account, output either as a widget for drop-in embedding, or as JSON for consumption by your code.
The Admin API is used only for managing feeds, not consuming them. So there is no endpoint here that will return the actual posts from a feed. Instead, once you have created a feed, you can use it with an embedded widget by specifying the feed ID, or by sending a GET to feeds.behold.so/FEED_ID
in the case of a JSON feed.
The feed object
Attributes
Fields marked read-only
are generated server-side and cannot be set during create or update requests. Fields marked immutable
are set during feed creation and then cannot be changed.
id
string read-only
id
The unique ID of this feed.
title string
A title / label for the feed. Not guaranteed to be unique.
sourceId
string immutable
sourceId
The ID of the source associated with this feed.
associatedAccountId
string immutable
associatedAccountId
The ID of the associated Instagram account to use. Only exists on feeds with advanced sources, which may have one or more associated Instagram accounts.
sourceType
enum read-only
sourceType
The type of the source associated with this feed. Either instagramBasic
or instagramAdvanced
.
contentSource
enum immutable
contentSource
The source of posts for this feed. Either user
or hashtag
. Default user
.
user
feeds are populated with posts from a single Instagram account.
hashtag
feeds are populated with public posts from one or more hashtags. You can learn more on our hashtag feeds page.
hashtags
array of strings immutable
hashtags
An array of the hashtags used to populate this feed.
outputType
enum immutable
outputType
The type of feed. Either json
or widget
.
created
timestamp read-only
created
A timestamp marking when the feed was created, in milliseconds since the UNIX epoch.
mediaCount
integer read-only
mediaCount
The total number of posts published by this account. This is not the number of posts that will be returned by the feed. That is determined by settings.maxPosts
.
views
integer | map read-only expandable
views
By default the views
field is an integer representing the total number of views this feed has received during the current month (all intervals are in UTC time). When expanded, it provides a breakdown of usage by month and day. Both days and months are 1-indexed. In expanded form, only months and days with views are included. So while entries are sorted in ascending order, they may not be consecutive. For example you might have the 1st and 2nd of the month, and then skip to the 4th if there was no usage on the 3rd.
List queries with expanded views only return data for the current month. Single /feeds/:feedId
requests return up to twelve months of usage data.
Example of a views field:
"views": 38
"views": { "total": 110, "months": [ { "year": 2024, "month": 10, "total": 72, "days": [ { "day": 30, "views": 18 }, { "day": 31, "views": 54 } ] }, { "year": 2024, "month": 11, "total": 38, "days": [ { "day": 1, "views": 15 }, { "day": 2, "views": 20 }, { "day": 4, "views": 3 } ] } ]}
"views": { "total": 0, "months": []}
settings map
A map of feed settings. Show child attributes Hide child attributes
settings.filter map
A map of settings that filter the content returned by this feed.
Show child attributes Hide child attributes
settings.filter.allowedTypes array of enums
This setting dictates which post types are included in this feed. At least one type is required. Allowed values are IMAGE
, VIDEO
, REEL
and CAROUSEL_ALBUM
. Default ["IMAGE", "VIDEO", "REEL", "CAROUSEL_ALBUM"]
.
settings.filter.captionExcludeText array of strings
Only posts that do not contain any of the text snippets you add here will be included in your feed. This is case-sensitive and can include spaces. A maximum of 3 strings may be excluded. Default [ ]
.
settings.filter.captionIncludeText array of strings
Only posts that contain at least one of the text snippets you add here
will be included in your feed. This is case-sensitive and can include spaces. A maximum of 50 strings may be included. Default [ ]
.
settings.filter.reelFeedStatus enum
Cooresponds to the Show off-feed reels
setting in the dashboard. When set to sharedToFeed
, only reels that appear on the main Instagram grid will be included in this feed.
When contentSource
is set to hashtag
, reelFeedStatus
must be set to all
.
One of all
, sharedToFeed
. Default all
.
settings.maxPosts integer
Sets the number of posts to return. The maximum value is determined by your plan. The Platform
plan allows a max of 50 posts per feed. If you need more, get in touch: sales@behold.so. Default 6
.
settings.domainWhitelist array of strings
This option blocks feed requests that do not originate from one of the whitelisted domains. If you leave this blank, all requests are allowed.
Subdomains are independent and wildcards are not supported. So example.com
and www.example.com
must be entered separately. The protocol (e.g. https://
) is ignored.
localhost
is always whitelisted.
Default [ ]
.
Note
The domain whitelist provides a layer of defense against people just copy/pasting a feed, but there are ways around it. Because no API keys or secrets are exposed, this isn’t a serious security risk, however.
widgetSettings map
A map of widget settings. Only included in
widget feeds. Show child attributes Hide child attributes
widgetSettings.type
enum immutable required
widgetSettings.type
The style of widget. Currently only grid
widgets are supported for creation or update by the admin API. This attribute is required if you are updating any widgetSettings
attributes.
widgetSettings.constrainWidth boolean
If set to false
, the widget will always grow to fit the width of its containing element. If set to true
, the width will be capped at the value of maxWidth
setting. Default false
.
widgetSettings.maxWidth integer
The max width of the widget. Ignored if constrainWidth
is set to false
. Default 650
.
widgetSettings.alignment enum
The horizontal alignment of the widget within its container. One of left
, center
, right
. Ignored if constrainWidth
is set to false
. Default center
.
widgetSettings.numColumns integer
The number of columns posts will be arranged in for grid
widgets. Default 3
.
widgetSettings.gap map
The vertical and horizontal gap between posts.
Show child attributes Hide child attributes
widgetSettings.gap.x integer
The horizontal gap between posts. Default 20
.
widgetSettings.gap.y integer
The vertical gap between posts. Default 20
.
widgetSettings.postAspectRatio map
The aspect ratio of widget posts. If you want to use the format of reels, set to { x: 9, y: 16 }
.
Show child attributes Hide child attributes
widgetSettings.postAspectRatio.x integer
Post width. Default 1
.
widgetSettings.postAspectRatio.y integer
Post height. Default 1
.
widgetSettings.borderRadius integer
The post border radius / rounded corners. Default 0
.
widgetSettings.loadingColor enum
Color to show while a post loads. One of dominant
, muted
, vibrant
, mutedLight
, vibrantLight
, mutedDark
, vibrantDark
, tone
, transparent
. Default dominant
.
If tone
, the color is set by the loadingColorTone
setting.
If transparent
, no color is shown.
The rest of the options extract a color from the post media itself using different algorithms.
widgetSettings.loadingColorTone string
An RGB color as a string in the format r,g,b
. Defines the placeholder color to use if loadingColor
is set to tone
. The rendered color will be slightly lighter or darker depending on the contents of the post media. Default 225,73,57
.
widgetSettings.onHover enum
Defines the behavior on hover. One of showIcon
, showCaption
, or none
. Default showIcon
.
widgetSettings.hoverEffect enum
The effect to display on hover. One of fade
, zoomFade
, blur
, zoomBlur
, toGreyscale
, zoomToGreyscale
, fromGreyscale
, zoomFromGreyscale
, or none
. Default zoomFade
.
widgetSettings.hoverOverlayColor enum
The color of the overlay displayed on hover. One of default
, auto
, or custom
. Default default
.
default
is a semi-transparent black overlay.
auto
extracts a color from the post media using the dominant
algorithm.
custom
allows defining a custom color using the hoverOverlayCustomColor
setting.
This setting is ignored unless hoverEffect
is set to fade
or zoomFade
.
widgetSettings.hoverOverlayCustomColor string
An RGB color as a string in the format r,g,b
. Defines the overlay color to show on hover when hoverOverlayColor
is set to custom
. Default 0,0,0
.
widgetSettings.hoverOverlayOpacity integer
An integer ranging from 0 - 100
. Sets the opacity of the overlay to show on hover. This setting is ignored unless hoverEffect
is set to fade
or zoomFade
. Default 65
.
widgetSettings.previewVideosOnHover boolean
If set to true
, videos will autoplay muted on hover. Default true
.
widgetSettings.autoplayVideos boolean
If set to true
, videos will autoplay muted on load. Default false
.
widgetSettings.onPostClick enum
Defines the behavior when a post is clicked. One of linkToPost
, linkToProfile
, customLink
, openPopupGallery
, doNothing
. Default linkToPost
.
widgetSettings.customLinkURL string
Defines where a user will be sent when they click on a post and onPostClick
is set to customLink
. Default ""
.
widgetSettings.linkTarget enum
One of _blank
or _self
. Default _blank
. This dictates if post links should open in a new tab or not. If set to _blank
, links will open in a new tab.
widgetSettings.popupColorTheme enum
Defines the color theme of the popup gallery. Ignored unless onPostClick
is set to openPopupGallery
. One of auto
, light
, or dark
. Default auto
.
widgetSettings.breakpoints map
A map of breakpoint settings. The key of a breakpoint entry is a string representing the pixel width where the breakpoint applies, and the value is a map of options that will override the base options set on the widget. Breakpoints are applied based on the width of the widget itself, not the window.
The options that can be set in a breakpoint are maxPosts
, numColumns
, borderRadius
, postAspectRatio
, and gap
. If you omit an option, it will default to the primary value in widgetSettings
.
To remove a specific breakpoint, set the value to null
.
Here’s an example breakpoint configuration:
breakpoints: { "900": { "maxPosts": 6, "numColumns": 3, }, "500": { "maxPosts": 4, "numColumns": 2, "borderRadius": 0, "postAspectRatio": { "x": 1, "y": 1}, "gap": { "x": 0, "y": 0 } }, "650": null}
In this example, at 900px the widget will have maxPosts set to 6 and numColumns set to 3. Then, once the widget hits 500px, a different set of settings is applied. A previously set breakpoint at 650px is deleted.
Create a feed
POST /feeds
Tip
You can get a ready-to-use feed config in the Behold dashboard by clicking on the three dots next to a feed title and selecting “Copy config”. The copied JSON can be sent to this endpoint to create a new feed.
This lets you style a widget using our GUI and then create new feeds with the same setup via API. You’ll usually want to change the title
and sourceId
.
Request attributes
This endpoint accepts a feed object in the request body as a JSON-encoded string. All feed attributes may be included except those marked read-only.
sourceId
, title
, and outputType
are required. If you are creating a feed using an advanced source, associatedAccountId
is required. Any field you omit will use the default value.
Return value
Returns the feed object with all fields after successful creation.
Example request
curl -X POST https://api.behold.so/v1/feeds \-H 'Authorization: Bearer YOUR_API_ACCESS_TOKEN' \-H 'Content-Type: application/json' \-d '{ "sourceId": "17841429465705030", "title": "Humberto's Healthy Halva JSON feed", "outputType": "json", "settings": { "maxPosts": 16, "filter": { "allowedTypes": ["IMAGE", "CAROUSEL_ALBUM"] } }}'
{ "data": { "title": "Humberto's Healthy Halva JSON feed", "id": "WZSiThw9hIPO9GDJM3w7", "sourceId": "17841429465705030", "sourceType": "instagramBasic", "contentSource": "user", "outputType": "json", "created": 1733149658, "mediaCount": 74, "views": 0, "settings": { "filter": { "allowedTypes": ["IMAGE", "CAROUSEL_ALBUM"], "captionExcludeText": [], "captionIncludeText": [], "reelFeedStatus": "all" }, "maxPosts": 16, "domainWhitelist": [] } }}
curl -X POST https://api.behold.so/v1/feeds \-H 'Authorization: Bearer YOUR_API_ACCESS_TOKEN' \-H 'Content-Type: application/json' \-d '{ "sourceId": "17841429465705030", "title": "Exceptional Ducks Inc. widget", "outputType": "widget", "contentSource": "user", "settings": { "maxPosts": 8 }, "widgetSettings": { "constrainWidth": false, "numColumns": 4, "gap": {"x": 0, "y": 0}, "onPostClick": "openPopupGallery" }}'
{ "data": { "title": "Exceptional Ducks Inc. widget", "id": "v2j4CI9GkHZCfIyMRBC9", "sourceId": "17841429465705030", "sourceType": "instagramBasic", "outputType": "widget", "contentSource": "user", "created": 1733151858, "mediaCount": 74, "views": 0, "settings": { "filter": { "allowedTypes": ["IMAGE", "VIDEO", "REEL", "CAROUSEL_ALBUM"], "captionExcludeText": [], "captionIncludeText": [], "reelFeedStatus": "all" }, "maxPosts": 8, "domainWhitelist": [] }, "widgetSettings": { "type": "grid", "constrainWidth": true, "maxWidth": 650, "alignment": "center", "onHover": "showIcon", "hoverEffect": "zoomFade", "hoverOverlayColor": "default", "hoverOverlayCustomColor": "0,0,0", "hoverOverlayOpacity": 65, "previewVideosOnHover": true, "autoplayVideos": false, "onPostClick": "openPopupGallery", "customLinkURL": "", "linkTarget": "_blank", "popupColorTheme": "auto", "breakpoints": {}, "numColumns": 4, "gap": { "x": 0, "y": 0 }, "borderRadius": 0, "postAspectRatio": { "x": 1, "y": 1 }, "loadingColor": "dominant", "loadingColorTone": "225,73,57" } }}
Update a feed
PATCH /feeds/:feedId
Request attributes
This endpoint accepts a feed object in the request body as a JSON-encoded string. All feed attributes may be included except those marked read-only or immutable.
Return value
Returns the feed object with all fields after successfully updating.
Example request
curl -X PATCH https://api.behold.so/v1/feeds/v2j4CI9GkHZCfIyMRBC9 \-H 'Authorization: Bearer YOUR_API_ACCESS_TOKEN' \-H 'Content-Type: application/json' \-d '{ "title": "Dr. Runcible's Spoon Emporium widget", "settings": { "maxPosts": 12 }, "widgetSettings": { "numColumns": 6, "gap": {"x": 20, "y": 20}, }}'
{ "data": { "title": "Dr. Runcible's Spoon Emporium widget", "id": "v2j4CI9GkHZCfIyMRBC9", "sourceId": "17841429465705030", "sourceType": "instagramBasic", "outputType": "widget", "contentSource": "user", "created": 1733151858, "mediaCount": 74, "views": 0, "settings": { "filter": { "allowedTypes": ["IMAGE", "VIDEO", "REEL", "CAROUSEL_ALBUM"], "captionExcludeText": [], "captionIncludeText": [], "reelFeedStatus": "all" }, "maxPosts": 12, "domainWhitelist": [] }, "widgetSettings": { "type": "grid", "constrainWidth": true, "maxWidth": 650, "alignment": "center", "onHover": "showIcon", "hoverEffect": "zoomFade", "hoverOverlayColor": "default", "hoverOverlayCustomColor": "0,0,0", "hoverOverlayOpacity": 65, "previewVideosOnHover": true, "autoplayVideos": false, "onPostClick": "openPopupGallery", "customLinkURL": "", "linkTarget": "_blank", "popupColorTheme": "auto", "breakpoints": {}, "numColumns": 6, "gap": { "x": 20, "y": 20 }, "borderRadius": 0, "postAspectRatio": { "x": 1, "y": 1 }, "loadingColor": "dominant", "loadingColorTone": "225,73,57" } }}
Retrieve a feed
GET /feeds/:feedId
Parameters
Accepts no parameters.
Return value
Returns a JSON object containing all fields for a single feed. The views
field is expanded by default.
Example request
curl https://api.behold.so/v1/feeds/AkBeuRE53HsLIts6tgvV \-H 'Authorization: Bearer YOUR_API_ACCESS_TOKEN'
{ "data": { "title": "Wildegard's Wand Warehouse JSON feed", "id": "AkBeuRE53HsLIts6tgvV", "sourceId": "17841429465705030", "sourceType": "instagramBasic", "outputType": "json", "contentSource": "user", "created": 1732300006, "mediaCount": 74, "views": { "total": 10, "months": [ { "year": 2024, "month": 10, "total": 8, "days": [{ "day": 15, "views": 8 }] }, { "year": 2024, "month": 11, "total": 2, "days": [{ "day": 27, "views": 2 }] } ] }, "settings": { "filter": { "allowedTypes": ["IMAGE", "VIDEO", "REEL", "CAROUSEL_ALBUM"], "captionExcludeText": [], "captionIncludeText": [], "reelFeedStatus": "all" }, "maxPosts": 9, "domainWhitelist": [] } }}
List all feeds
GET /feeds
Returns all available feeds, sorted by title
in ascending alphabetical order.
Parameters
limit integer
Limits the number of responses. Limit can range between 1 and 100. The default is 10.
fields comma-delimited string
Specifies a subset of fields to return. Set to all
to return all fields. The default is id
.
expand comma-delimited string
Specifies fields to expand. Currently only views
can be expanded. For more information see field expansion.
cursor string
See pagination.
Return value
Returns an array of all active feeds in your account.
Example request
curl -G https://api.behold.so/v1/feeds \-H 'Authorization: Bearer YOUR_API_ACCESS_TOKEN'\-d limit=3 \-d fields="title,outputType,mediaCount,views"
{ "data": [ { "id": "drF2DLDcB0McNcnP8c2A", "title": "Advanced Widget 2", "outputType": "widget", "mediaCount": 331, "views": 0 }, { "id": "xehTvOCY4eICwMiBILRv", "title": "Advanced Widget 3", "outputType": "widget", "mediaCount": 174, "views": 131 }, { "id": "JGxEk2YDpALyfMwDO8zx", "title": "My JSON feed", "outputType": "json", "mediaCount": 24, "views": 243 } ], "cursors": { "before": null, "after": "bmV4dDpNeSBKU09OIGZlZWQgMjpXWlNpVGh3OWhJUE85R0RKTTN3Nw" }}
Delete a feed
DELETE /feeds/:feedId
Parameters
Accepts no parameters.
Return value
Returns a JSON object containing the id
, title
, sourceId
, and sourceType
of the feed. Feeds created with advanced sources will also return associatedAccountId
.
Example request
curl -X DELETE https://api.behold.so/v1/feeds/poHnXKjskmnyORucY8z6 \-H "Authorization: Bearer YOUR_API_ACCESS_TOKEN"
{ "data": { "id": "poHnXKjskmnyORucY8z6", "title": "Bubba's autobody & smashburgers", "sourceType": "instagramBasic", "sourceId": "17841452978726144" }}
curl -X DELETE https://api.behold.so/v1/feeds/TD7Crfo2Y15PsvdNVyn0 \-H "Authorization: Bearer YOUR_API_ACCESS_TOKEN"
{ "data": { "id": "TD7Crfo2Y15PsvdNVyn0", "title": "#TooMuchCheese hashtag feed", "sourceType": "instagramAdvanced", "sourceId": "122098019756544079", "associatedAccountId": "17841429465705030" }}