Get started

Response shape

The envelope, the meta block, base fields, nulls and raw payloads.

The envelope

Every successful response is { data, meta }. On a single-object route data is one object; on a paged route it is an array.

response
{
  "data": { … },            // one object, or an array on paged routes
  "meta": {
    "credits_used": 1,
    "credits_remaining": 2499,
    "cache": "MISS",          // or "HIT"
    "data_age_s": 0,          // seconds since we fetched it upstream
    "request_id": "req_01K5…",
    "next_cursor": "eyJ…"     // paged routes only, absent on the last page
  }
}

The same numbers are also sent as headers, for clients that stream or log headers only: X-Credits-Used, X-Credits-Remaining, X-Cache, X-Data-Age and X-Request-Id.

Fields on every object

Whatever the type, every object carries these. source says where the data came from: official (the platform’s own API), own (our scraper) or upstream:<provider>.

FieldTypeNotes
platformPlatform
idstring
urlurl
fetched_atdatetime
source"official" | "own" | "upstream:…"
rawunknownoptional
enrichmentEnrichmentnullable, optional

Nulls, not missing fields

A field a platform does not have is null, never absent and never renamed. Bluesky has no view counts, so a Bluesky post has engagement.views: null; a TikTok post has a number there. Your code reads the same path everywhere and handles one extra case.

null means “this platform does not expose it” or “it was hidden”. It never means zero. A post with no likes has likes: 0.

The raw payload

Add include_raw=true to any read to get the platform’s untouched payload under raw on each object (and on meta.raw for paged routes). Use it for the rare field the unified schema does not carry yet. It is not part of the schema promise and may change when the platform changes.

Types

There are 17 unified types. Each operation always returns the same one, on every platform that serves it. The full field list is in Unified types.