GET /v1/social-accounts/:accountId/health
Content-health snapshot — score, tier, engagement buckets, and a tailored recommendation.
/v1/social-accounts/:accountId/health- Auth
- Bearer
- Scope
- social:read
Returns the latest content-health snapshot for a connected social account. Layers refreshes this every 30 minutes via a Temporal cron — partners read; they don't compute.
The response is purpose-built for surfacing two things to a creator:
- Where am I? — a continuous
score(0–100) and a coarsetierlabel (shadowbanned | new | cold | warming_up | warm | hot). - What should I do? — a single human-readable
recommendationstring ("this is your state, this is what you should do"). Deterministic — generated from a finite template set with the account's actual numbers interpolated. No LLM, no hallucination.
Health is computed from post metrics only — view counts, comment/save/share counts, posting cadence. It does not use follower count and has no audience denominator. Engagement is judged with absolute counts against tier-relative thresholds, not ratios — so a 1M-view post with 50 comments and a 100-view post with 1 comment can both read as healthy at their respective scales.
accountIdstringrequiredPrefixed social account id (e.g. `sa_9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e`).
Example request
curl "https://api.layers.com/v1/social-accounts/sa_9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e/health" \
-H "Authorization: Bearer lp_..."const health = await layers.social.getHealth({
accountId: "sa_9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e",
});
if (health.tier === "shadowbanned") {
showBanner({
severity: health.shadowbanSeverity,
message: health.recommendation,
});
}health = layers.social.get_health(
account_id="sa_9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e",
)
if health["tier"] == "shadowbanned":
show_banner(severity=health["shadowbanSeverity"], message=health["recommendation"])Response
{
"socialAccountId": "sa_9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e",
"score": 73,
"tier": "warm",
"isShadowBanned": false,
"shadowbanSeverity": null,
"coldStart": false,
"managedDistribution": false,
"engagementHealth": {
"comments": "par",
"saves": "above_par",
"shares": "par"
},
"signals": {
"medianRecentViews": 4200,
"averageRecentViews": 5100,
"totalRecentViews": 51000,
"postsAnalyzed": 10,
"daysSinceLastPost": 1,
"daysOfHistory": 60,
"postingFrequency": 0.8,
"postingVariance": 1.2,
"medianRecentComments": 12,
"medianRecentSaves": 25,
"medianRecentShares": 6
},
"recommendation": "You're pulling 4,200 median views with healthy engagement — breaking through. Push to 2 posts per day (not back-to-back) and double down on the formats that are working. Homogeneity is fine right now. Spend 10 minutes a day leaving substantive comments on 5–10 peer creators in your niche. We can't measure this from the platform APIs but it's a leading indicator of algorithmic lift.",
"analyzedAt": "2026-05-07T14:30:00Z"
}Cold start vs new
The new tier covers two states the partner often needs to distinguish:
| State | tier | coldStart | signals.postsAnalyzed | What it means |
|---|---|---|---|---|
| Pre-launch | new | true | 0 | Account hasn't posted yet — there is no signal at all. Don't render any progress UI. |
| Early run | new | false | 1–4 | Posts exist but too few (< 5) or too short a history (< 14 days) to read meaningfully. |
Score is 0 for cold-start accounts; the recommendation tells the user (or the distribution layer, for managed accounts) to keep posting.
Managed Social Distribution accounts
When managedDistribution: true, the account is part of Layers' Managed Social Distribution program — content publishes via an upstream provider (DS, SSH, HA, FM, TP) with vendor-defined per-day caps. The customer cannot unilaterally change cadence on these accounts.
The recommendation language is softened accordingly:
- Customer-controlled accounts get prescriptive language: "Push to 2 posts per day."
- Managed accounts get observation-style language: "If your distribution provider supports a higher cadence, request it."
UI guidance: don't render "post more" or "schedule a post" controls for managed accounts — render the linked distribution-layer status instead. The managedDistribution flag exists exactly so partners can branch their UX without parsing the recommendation text.
Tier ladder
The five non-special tiers are ordered for psychological progress — each step up reads as visible improvement.
| Tier | Median views (last 10 posts) | What it means | Recommended cadence |
|---|---|---|---|
shadowbanned | Recent posts pulling 0 views | Platform is throttling reach. See shadowbanSeverity for severity. | Pause posting (24h or 48h depending on severity). |
new | < 5 posts OR < 14 days of history | Too early to read signal. | 1 post/day for 2 weeks; we'll re-evaluate. |
cold | < 100 | We don't have enough signal yet. | 1 post/day, experiment broadly with formats. |
warming_up | 100 – 1,000 | Some format is starting to land. | 1 post/day, narrow your experiments toward what's working. |
warm | 1,000 – 10,000 | Breaking through. | 2 posts/day (not back-to-back), double down. |
hot | ≥ 10,000 | You've broken through. Algorithm is lifting you. | 3 posts/day, expect "what app is this?" comments. |
Shadowban severity
shadowbanSeverity | Trigger | Recommendation |
|---|---|---|
possible | Most-recent post has 0 views and is more than 1 hour old. | Wait about a day before posting again. Stay out of the feed. |
definite | ≥ 2 consecutive recent posts have 0 views. | Pause posting and feed engagement for 48 hours. Resume with a single test post. |
null | Not shadowbanned. | — |
Shadowban detection is gated by a new-account guard — accounts with fewer than 5 posts or less than 14 days of history can't be classified as shadowbanned (small audiences look identical to throttled ones).
Engagement health
Per-axis (comments, saves, shares), each post is bucketed against absolute thresholds for its view tier — not a ratio. The medians of those per-post buckets across the recent window become the field values.
tier | par comments | par saves | par shares |
|---|---|---|---|
cold | 0 | 0 | 0 |
warming_up | 1 | 1 | 0 |
warm | 10 | 20 | 5 |
hot | 50 | 100 | 30 |
A bucket value of above_par means the median count is at least 2× par; par is between par and 2× par; below_par is below par. When a platform doesn't expose saves on a given post (TikTok historically didn't on some surfaces), saves reports par rather than below_par — neutrality, not penalty.
Score formula
viewMomentum = log10(medianRecentViews + 1) / log10(100_000) # 0..1
engagementHealth = avg of {comments, saves, shares} bucket scores # 0..1
consistency = blend of postingFrequency and daysSinceLastPost # 0..1
score = round(100 × (0.5·viewMomentum + 0.3·engagementHealth + 0.2·consistency))
score -= 30 if shadowbanned
score = clamp(score, 0, 100)The score is informational — tier and recommendation are what to render in your UI. Score is most useful for ranking accounts within a portfolio or trending an account over time.
Recommendation
recommendation is a single string, deterministic, and personalised by interpolating the account's actual numbers. It always covers two layers:
- Primary line — state + cadence action ("you're at X median views — do Y").
- Optional appendices — flagged when the data warrants it: spotty distribution (high
postingVariance), and a peer-engagement nudge (suppressed when shadowbanned/new).
Render it as one block of text. It's safe to show verbatim.
When the snapshot doesn't exist
Returns 404 if the account hasn't been analyzed yet — typically the case for the first ~30 minutes after the Account Health Monitor system layer was provisioned for the account. Poll back, or call again after the first scheduled run.
Errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHENTICATED | Missing or invalid key. |
| 403 | FORBIDDEN_SCOPE | Key lacks social:read. |
| 404 | NOT_FOUND | Account not in your organization, or no analysis row exists yet. |
| 429 | RATE_LIMITED | Read budget exhausted. |
See also
GET /v1/projects/:projectId/social-accounts— list accounts to find theirsocialAccountId.POST /v1/projects/:projectId/social/reauth-url— fix areauth_requiredaccount before its health can recover.