Skip to main content

Analytics API

The analytics endpoints expose the insight data post.buzz collects per account and per post, plus computed recommendations. This is the API counterpart of Analytics.

Requires authentication.


Insights summary​

GET /api/v1/analytics/summary?windowDays=30

Returns the latest insight row per account for the requested window, as a plain array inside data.

ParameterTypeDefaultDescription
windowDaysinteger30Look-back window in days

Example​

curl "https://<your-api-origin>/api/v1/analytics/summary?windowDays=7" \
-H "Authorization: Bearer sx_live_YOUR_API_KEY"

Response — 200 OK​

{
"data": [
{
"accountId": "acc_abc123",
"platform": "instagram",
"impressions": 48200,
"likes": 1240,
"comments": 86,
"capturedAt": "2026-07-12T00:00:00.000Z"
}
]
}

Field availability varies by platform — rows contain what each platform reports.


Best posting times​

GET /api/v1/best-times?accountId=<id>

Returns computed recommendations for when to post, based on your accounts' historical engagement.

ParameterTypeRequiredDescription
accountIdstringnoRestrict analysis to one account
accountIdsstringnoComma-separated list; combine specific accounts

Response — 200 OK​

{
"data": {
"hasEnoughData": true,
"modelVersion": "bt-2",
"timeZone": "America/New_York",
"confidence": "medium",
"sampleCount": 42,
"windows": [
{
"dow": 2,
"startHour": 18,
"endHour": 21,
"score": 0.31,
"reason": "Based on your mature post performance"
}
],
"nextSlots": [
{ "at": "2026-10-27T22:40:00.000Z", "score": 0.31, "windowIndex": 0 }
],
"dailySlots": [
{ "at": "2026-10-25T20:00:00.000Z", "score": 0.12, "windowIndex": -1 }
],
"grid": [{ "dow": 2, "hour": 18, "score": 0.31, "n": 6.2 }],
"recommendations": [
{
"day": "Tuesday",
"hour": 22,
"reason": "Based on your mature post performance"
}
]
}
}

Scores come from a per-account model that compares each post's engagement against the account's own baseline (see grid for the full 168-cell week, windows for merged posting windows in the audience's timezone, and nextSlots for the strongest upcoming UTC instants over the next two weeks, and dailySlots for each audience-local day's single strongest open instant, including days with no top pick). recommendations keeps the legacy shape for compatibility: the next five slots' UTC day name and hour.

With little or no history the model falls back to platform benchmark priors: confidence is "low" and hasEnoughData is false, while windows and nextSlots still return prior-driven suggestions. confidence rises to "medium" and "high" as the account's own mature posts dominate the recommended windows.

When you pass accountId or accountIds, every nextSlots and dailySlots entry respects each selected account's minimum post gap and daily cap, so it is safe to schedule one cross-post at that instant. Without a selection, the response combines all connected accounts into one grid, expressed in the timezone most of them use, and both slot lists reflect only that combined audience's timing.


Post analytics​

GET /api/v1/posts/{id}/analytics

Returns the insight row recorded for one published post inside data; 404 with { "error": "Insight not found" } if none exists yet. See Posts API.


Account analytics​

GET /api/v1/accounts/{id}/analytics

Returns post.buzz's computed analysis of one account's recent performance — for example its bestTone and bestPostType — inside data.


Force an insight refresh​

POST /api/v1/accounts/{id}/analytics/refresh

Queues an immediate re-fetch of platform insights for one account (normally insights sync on a schedule). Returns a job descriptor inside data.

Request body​

FieldTypeDefaultDescription
windowDaysinteger90How far back to fetch
limitinteger50Max posts to fetch insights for

Response — 200 OK​

{
"data": {
"jobId": "job_...",
"status": "queued"
}
}

Rate limit — 429​

Manual refreshes are capped at 3 per rolling 24 hours per account (configurable per account; 0 disables). Exceeding the cap:

{
"error": {
"code": "rate_limited",
"message": "Daily insight refresh limit reached for this account (3/3). Next slot in 14h 2m."
}
}

The message always reports your usage count and when the next slot opens. 404 not_found for an unknown account; 500 server_error if queuing fails.

tip

Don't poll-refresh on a timer — scheduled syncs keep insights fresh on their own. Use forced refresh after a known viral spike or an import.