GET /v1/bloggers

Returns a paginated list of the accounts (blogger records) in your organization, with their aggregated video statistics. Supports filtering, exact-campaign matching and sorting.

An account is one tracked (or previously tracked) social account. To see accounts grouped under a named creator entity, use GET /v1/creators instead — every account here may belong to zero, one or several creators.

To start tracking a new account, use POST /v1/bloggers/track first and poll GET /v1/bloggers/jobs/{job_id} until succeeded.

📋 Overview

Property Value
Method GET
Endpoint https://api.influtics.com/v1/bloggers
Auth Required ✅ Yes
Plan Required 💳 Paid — free-tier keys get 402 PAID_PLAN_REQUIRED
Credits Cost 0 credits

🔐 Headers

Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

📝 Query Parameters

Parameter Type Required Description
tracked boolean No true = actively tracking only. false = not actively tracking (paused and never-tracked). Omit for no filter. Also accepts 1 / 0.
creator_id string (uuid) No Return only accounts linked to this creator. See GET /v1/creators/{id} for how to obtain one.
platform string | string[] No Filter by platform. Comma-separated (?platform=tiktok,instagram) or repeated (?platform=tiktok&platform=instagram). Unknown values are rejected with 400 VALIDATION_ERROR — see the error table below.
campaign string | string[] No Exact campaign name match. Comma-separated or repeated. See ⚠️ campaign is an exact match, not a substring under Notes below.
sort string No Sort key (default tracked_at). One of avg_views, median_views, number_of_subscribers, total_views, video_count, tracked_at.
sort_order string No asc or desc (default desc). Anything other than asc sorts descending — see Sorting, clamping and defaults are silent under Notes below.
limit number No Page size. Default 50, clamped to 1–100.
offset number No Rows to skip. ≥ 0, negative values are treated as 0.

tracked and creator_id intersect: ?tracked=true&creator_id=<uuid> returns only accounts that are actively tracked and linked to that creator, never the union.

Example Request

# Actively-tracked TikTok accounts, biggest audience first
curl -X GET "https://api.influtics.com/v1/bloggers?tracked=true&platform=tiktok&sort=number_of_subscribers&sort_order=desc&limit=25" \
  -H "Authorization: Bearer YOUR_API_KEY"
# Every account linked to one creator (campaign names must be exact and encoded)
curl -X GET "https://api.influtics.com/v1/bloggers?creator_id=1f0c9a5e-6b2d-4a17-9c3e-7d8b2f4a1c90&campaign=%D0%90%D0%B2%D0%B8%D1%82%D0%BE%20%D0%9D%D0%B5%D0%B4%D0%B2%D0%B8%D0%B6" \
  -H "Authorization: Bearer YOUR_API_KEY"
# Second page
curl -X GET "https://api.influtics.com/v1/bloggers?limit=50&offset=50" \
  -H "Authorization: Bearer YOUR_API_KEY"

📤 Response

{
  "success": true,
  "data": {
    "accounts": [
      {
        "id": "1b7c4e90-3a55-4d21-9f08-6c2ad5b19e34",
        "channel_name": "Kate Comfortt",
        "channel_username": "katecomfortt",
        "channel_thumbnail": "https://xhrjtpcqcdqwcdiqrhfw.supabase.co/storage/v1/object/public/avatars/katecomfortt.jpg",
        "url": "https://www.instagram.com/katecomfortt",
        "platform": "instagram",
        "is_tracked": true,
        "tracking_id": "8c3f2b71-0d64-4a92-b1f7-2e5c9a4d6b13",
        "tracked_at": "2026-02-14T09:31:00Z",
        "last_scraped_at": "2026-10-19T22:00:00Z",
        "campaign": "Авито Недвиж",
        "budget_per_video": 12000,
        "daily_videos_count": 3,
        "video_count": 42,
        "number_of_subscribers": 128400,
        "total_views": 18732000,
        "median_views": 312000,
        "avg_views": 446000,
        "created_at": "2026-01-08T11:02:41Z",
        "updated_at": "2026-10-19T22:03:12Z"
      },
      {
        "id": "5e2d8a13-7c40-4b96-8f51-2d9a6e3b7c02",
        "channel_name": "Блогер без статистики",
        "channel_username": null,
        "channel_thumbnail": null,
        "url": null,
        "platform": "vk",
        "is_tracked": false,
        "tracking_id": "1a9d4e77-6b02-4c58-8f31-7d0e2b4a6c95",
        "tracked_at": "2026-06-02T14:12:09Z",
        "last_scraped_at": "2026-09-28T03:10:44Z",
        "campaign": null,
        "budget_per_video": null,
        "daily_videos_count": 0,
        "video_count": 0,
        "number_of_subscribers": 0,
        "total_views": 0,
        "median_views": 0,
        "avg_views": 0,
        "created_at": "2026-05-30T08:44:00Z",
        "updated_at": "2026-09-28T03:10:44Z"
      }
    ],
    "pagination": {
      "total": 387,
      "limit": 50,
      "offset": 0,
      "has_more": true
    }
  },
  "meta": {
    "request_id": "9f7e8d4c-1a2b-4c3d-8e5f-6a7b8c9d0e1f"
  }
}

account fields

Field Type Description
id string | null Internal account UUID. Use it for GET /v1/bloggers/{id}. null only for an account linked to a creator that has no statistics row at all.
channel_name string | null Creator's display name.
channel_username string | null Username without @. null when unknown — this is common for accounts imported from video URLs rather than added by username.
channel_thumbnail string | null Avatar URL.
url string | null Canonical profile URL.
platform string | null One of tiktok, instagram, youtube, telegram, vk, ok, dzen, facebook, threads, pinterest.
is_tracked boolean Actively tracking. A paused account reads false — see Notes below.
tracking_id string | null UUID of the tracked_accounts row.
tracked_at string | null When tracking started (ISO 8601). This is the default sort key.
last_scraped_at string | null When platform stats were last refreshed — not when this request was made.
campaign string | null Exact campaign name, or null when the account is not in a campaign.
budget_per_video number | null Per-video budget configured for the account, or null if none.
daily_videos_count number | null Videos per day expected by the tracking schedule.
video_count number | null Number of videos with statistics in the org.
number_of_subscribers number | null Subscriber / follower count at last refresh.
total_views number | null Sum of views across the account's videos.
median_views number | null Median views across the account's videos.
avg_views number | null Mean views across the account's videos. Published as avg_views — the underlying column is named average_views. See Notes below.
created_at string | null When the account row was created (ISO 8601).
updated_at string | null When the account row was last written (ISO 8601).

pagination fields

Pagination lives inside data, not in meta.

Field Type Description
total number Total matching view rows, not necessarily distinct accounts — see Notes below.
limit number Page size actually used, after clamping. Echo it back rather than assuming your requested value.
offset number Offset actually used, after clamping.
has_more boolean true when offset + returned rows < total.

An empty page is not an empty result set: total is computed over the whole filtered set independently of offset, so paging past the end still reports the real total and has_more: false.

⚠️ Error Responses

All errors share the standard envelope { success: false, error: { code, message, request_id, ... } }. The table below lists every documented code and the conditions that trigger it.

Status code Trigger Additional error fields
400 VALIDATION_ERROR sort is not one of the six supported keys field: "sort"
400 VALIDATION_ERROR platform contains a value outside the supported platform list field: "platform"
400 VALIDATION_ERROR tracked is not true, false, 1 or 0 field: "tracked"
400 VALIDATION_ERROR campaign is present but contains no usable name (e.g. campaign=,) field: "campaign"
401 INVALID_API_KEY The Authorization: Bearer header is missing, empty, or malformed —
402 PAID_PLAN_REQUIRED Free-tier API key attempted the call upgrade_url
403 INVALID_OR_INACTIVE_API_KEY The API key is well-formed but unknown, revoked, or deactivated —
503 RETRY Subscription status could not be verified; retry shortly —
500 INTERNAL_ERROR Unexpected database or service failure —

A 403 means the key was recognised and can no longer be used — a revoked or deactivated credential — which is a different client-side fix from a 401, where the Authorization: Bearer header never arrived or was malformed. The two are deliberately distinct: a credential that never arrived versus one that arrived and is unusable.

An unknown id in a by-id path, or a path that matches no route at all, returns 404 NOT_FOUND.

📌 Notes

is_tracked means actively tracking, not "known to you"

This is the single most misread field on this endpoint. is_tracked is true only while tracking is running. An account you started tracking and later paused reads is_tracked: false — the same value as an account you never tracked. The response never distinguishes the two.

So:

  • ?tracked=false returns paused and never-tracked accounts together, not just the paused ones.
  • An account can appear in an unfiltered list with is_tracked: false while its videos are still being fetched.
  • Filtering by is_tracked to build a "currently tracked" roster is correct; treating it as "is in our database" will over-report.

avg_views, not average_views

The published field name is avg_views. It is the account's mean views per video (ROUND(AVG(views))). median_views is the 50th percentile, and total_views the sum.

avg_likes, avg_comments and avg_reposts are not returned

These three fields are deliberately absent from this endpoint. The statistics view behind it aggregates views only — it has no columns that could produce an engagement average — so there is no correct value to send. They are omitted rather than emitted as 0.

If you need engagement averages, use GET /v1/bloggers/by-username/{username}, which computes avg_likes, avg_comments and avg_reposts through a different query. There, 0 means "no video data to average". Treat the absence here as "not computable", and the 0 there as "genuinely zero" — do not unify them.

avg_views itself is present on both endpoints with the same meaning, so the two responses can be compared field-for-field apart from those three.

⚠️ campaign is an exact match, not a substring

?campaign=Авито does not match Авито Недвиж. The value is compared for equality against the stored campaign name. If you need a prefix or substring match, fetch and filter client-side.

Two consequences that look like bugs but are not:

  1. Filtering by campaign legitimately returns a very small result set. campaign is set on only about 3% of accounts and is null on the other 97%. The rate varies by organization — a campaign-heavy organization can be far higher — but globally expect to filter away nearly everything. A handful of results, or none, is the filter working, not a broken endpoint.
  2. There is no way to ask for "accounts with no campaign." An unset campaign is stored as null, and no filter expresses null. Omitting campaign returns everyone; supplying it returns only the named ones.

Campaign names are arbitrary user text and may be Cyrillic. Percent-encode them — Авито Недвиж becomes %D0%90%D0%B2%D0%B8%D1%82%D0%BE%20%D0%9D%D0%B5%D0%B4%D0%B2%D0%B8%D0%B6.

total counts view rows, so an account can be counted twice

The statistics view groups by tracking row, so a blogger with two tracking rows produces two rows. pagination.total counts rows, and so can over-report the number of distinct accounts — about four such duplicate pairs exist at present. The same account can also appear twice in accounts[], and can straddle a page boundary.

Deduplicate on id before counting or paging if your workflow depends on exact account counts. has_more is computed against the same row count, so it stays internally consistent.

Sorting, clamping and defaults are silent

Three query parameters are normalized rather than rejected:

Sent Result
limit=abc Falls back to the default 50 — no error.
limit=5000 Clamped to 100.
limit=0 or limit=-1 Clamped to 1.
offset=-5 Treated as 0.
sort_order=downwards Treated as desc — any value other than asc sorts descending, with no error.

Only sort, platform, tracked and an empty campaign produce a 400. Check the echoed pagination.limit and pagination.offset if the exact page size matters to you.

nullsFirst: false is applied to every sort, so accounts with no value for the sort key (for example avg_views on an account with no videos) always appear last, in both directions.

Other characteristics

  • The response is scoped to the calling organization. An account belonging to another organization is not visible and returns 404 NOT_FOUND from the by-id endpoint.
  • These endpoints only read tables the organization already pays for and call no platform API, so they cost 0 credits.
  • Statistics are as of the last platform refresh, which is what last_scraped_at reports — not the moment of this request.

Related: Account by ID → | Creator Lookup by Username → | List Creators → | Track an Account →