Skip to main content
GET
/
api
/
late
/
analytics
/
posts
Get per-post social analytics
curl --request GET \
  --url https://app.puffle.ai/api/late/analytics/posts \
  --header 'Authorization: Bearer <token>'
{
  "overview": {
    "totalPosts": 12,
    "totalImpressions": 48230,
    "totalLikes": 612,
    "totalComments": 48,
    "totalShares": 22,
    "totalClicks": 190,
    "avgEngagementRate": 0.014
  },
  "posts": [
    {
      "postId": "pst_1111",
      "latePostId": "late_abc",
      "title": "Product launch",
      "scheduledAt": "2026-04-01T14:00:00Z",
      "accountIds": [
        "late_acc_jane"
      ],
      "analytics": {
        "impressions": 8120,
        "likes": 102,
        "comments": 9,
        "shares": 4,
        "clicks": 31,
        "engagementRate": 0.018
      }
    }
  ],
  "hasAnalyticsAccess": true
}

Overview

Dual-mode endpoint:
  • Single post — pass ?postId=<internal uuid> or ?latePostId=<late id>. Returns analytics for that one post wrapped in Late’s envelope.
  • Aggregate — omit both. Iterates every posted row in the caller’s calendar, makes one Late request per post, and returns an aggregate overview plus a per-post breakdown.
Platform metrics lag the live counters by roughly 24 hours.

AI agent notes

~24h lag — engagement data from LinkedIn/Twitter/etc. lands in Late with a delay of up to a day. Avoid polling aggressively within the first 24 hours after publication.Analytics add-on — requires the Late analytics add-on on the caller’s plan. Absent add-on returns 402 with code: "analytics_addon_required".Aggregate mode is expensive — one Late API call per posted post in the caller’s calendar. For large calendars, prefer single-post mode and cache aggregates client-side.Account filtering — the aggregate response includes accountIds as Late’s IDs (not internal IDs) so the frontend can filter against Late’s account tab without re-mapping.404 vs null analytics — when Late reports “analytics not available yet” (e.g., post too new), the response is 404 with body { error: "...", analytics: null }, not 200. Handle both branches.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Query Parameters

postId
string<uuid>

Internal post UUID. When set, the server looks up the associated late_post_id and returns single-post analytics. Mutually exclusive with latePostId.

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
latePostId
string

Late's post ID. Use when you already have the Late ID and want to skip the internal lookup. Mutually exclusive with postId.

Response

Single-post or aggregated response. See oneOf examples — shape depends on whether postId/latePostId was passed.

Shape returned when postId or latePostId is supplied. Late's own envelope is passed through — the per-post metrics live at analytics.analytics.

analytics
object
required