# Responses & schemas

The envelope, unified shapes, honest nulls.

## One envelope, every endpoint

Standard routed `/v1` JSON responses share an envelope. Batch uses a separate wrapper containing per-item envelopes; SSE carries the envelope in its final result event. The fields inside `data` still depend on the endpoint. Success looks like this:

**Example success envelope**

```
{
  "success": true,
  "platform": "tiktok",
  "endpoint": "/v1/tiktok/profile",
  "data": { … },                  // the normalized payload — shapes below
  "credits_used": 1,
  "credits_remaining": 4230,
  "request_id": "req_bd41f9027ac3e6518f",
  "cached": false
}
```

Standard envelopes carry `credits_used`. Successful calls include`credits_remaining`; errors may omit it if the balance was not read. Use `credits/balance` for a current balance rather than assuming a missing value is zero. `request_id` is the correlation id to quote in support. `cached` is true only when the response was re-served from the short-lived response cache (see [Pagination & caching](https://www.monocrawl.com/docs/pagination-caching)). Errors use one envelope too, documented with every type on the [Errors](https://www.monocrawl.com/docs/errors) page. Confirmed uncharged or refunded failures report zero. If billing is pending reconciliation, `credits_used` can be null: retain`request_id` and inspect `error.details.billing_status` before continuing.

## Endpoint fields and downloadable schemas

Use the [endpoint schema directory](https://www.monocrawl.com/docs/schemas) for published field types and their reviewed or observed provenance, illustrative examples, units and nullable or optional fields. These definitions also appear on endpoint pages and in OpenAPI. For calculated output, the [formula reference](https://www.monocrawl.com/docs/computed-fields)explains sample sizes and denominators. Use the [testing guide](https://www.monocrawl.com/docs/testing) to validate fixtures and the [runnable workflows](https://www.monocrawl.com/docs/workflows) to connect calls.

## Sandbox responses identify themselves

The same envelope serves `/sandbox`, with two deliberate differences: `endpoint` echoes a `/sandbox/…` path (a saved sample can never masquerade as production data) and synthetic payloads carry `"synthetic": true` plus a warning inside `data`. Production `/v1` never serves synthetic data — an endpoint that cannot reach a real upstream answers an honest error instead.

## List responses and the cursor key

Many list endpoints use these four keys. Check the endpoint reference for named collections, extra metadata and single-page limits:

**Example list payload**

```
{
  "items": [ … ],                 // fields depend on this endpoint
  "count": 30,
  "cursor": "eyJwYWdlIjoy…",     // null when no usable next cursor was supplied
  "has_more": true               // null when continuation is unknown
}
```

`cursor` is how you page — pass it back as the `cursor` query parameter when that endpoint supports it. A supplied cursor is an opaque string, even where the upstream pages by number or timestamp underneath. `null` means no usable next cursor was supplied; it is **not proof that all history was retrieved**. Check `has_more` and warnings when present: `has_more: null` means continuation is unknown. Details are on [Pagination & caching](https://www.monocrawl.com/docs/pagination-caching).

## Text, numbers and uncertain dates

Plain-text review, biography and description fields remove known source HTML and decode entities. Explicit HTML and Markdown fields retain their formatting. IDs and cursors remain strings. Monetary amounts in Klarna price summaries and TikTok Shop SKU prices are numbers; currencies remain separate. Abbreviated TikTok Ads follower counts include `followers_text` and `followers_estimated: true`, so a converted count such as 6,700,000 is not mistaken for an exact measurement.

Where a source supplies relative dates for Maps Q&A, YouTube community posts or live videos, attraction reviews, listings and job details, the original wording is retained in a `_text` field. The timestamp is null unless an absolute date is known. A separately labelled estimate, such as `created_at_estimated` or `posted_at_estimated`, is anchored to retrieval time and stays fixed in cached responses. Its precision is supplied alongside it. Sort on the exact timestamp first, falling back to the estimate only if your application accepts approximate dates. Vague labels, dates without a known timezone and old cached labels without a retrieval anchor can remain null; null means unknown, not zero or today.

## Amazon marketplace

An explicit `country` or `location` selects the marketplace. If both are supplied, `country` wins. Otherwise an Amazon URL used as the identifier selects its marketplace. A bare ASIN or search without a location defaults to the United Kingdom (`GB`, `amazon.co.uk`). Use `location=United States` or `country=US` for US prices, availability and reviews. Responses include `marketplace.country` and`marketplace.domain` for the resolved request scope. Compare products and reviews only within the same marketplace.

## Public profile metadata

X profiles include `location`, `bio_link` and `cover_url`when returned by the source. TikTok profiles include `commerce_user` and`seller` flags; missing flags are null. These flags do not establish a location or business category. Facebook profiles include `cover_url`,`following` and `created_text` when available.

Facebook `likes_count` and `followers` describe different audiences. Follower totals may be rounded by the source; an exact like count does not establish an exact follower count. Missing counts and creation dates remain null. No additional profile request is made to fill these fields.

## Common field families, endpoint-specific payloads

Normalization preserves source fields in readable families, but it does not make every platform or fallback payload identical. These are recurring keys, not a required schema for every response. Use the endpoint's documented fields and handle unavailable data:

| Family | Where | Recurring keys |
| --- | --- | --- |
| `author` | profiles, and nested inside posts/comments | `id · handle · name · url · followers · verified · avatar_url` |
| post / video | many social feeds, searches and single-post reads | `id · url · caption/text · created_at · stats · author`; availability varies |
| YouTube video | official-API video and channel-upload reads | `id · title · description · published_at · channel · views · likes · comments_count` |
| comment | comment lists and reply threads | `id · text · created_at/published_at · likes · reply_count · author`; reply previews may be incomplete |
| transcript | supported transcript endpoints | `platform · url · transcript · has_transcript` |
| ad | meta_ads, tiktok_ads, linkedin_ads, google_ads | identity + creative + run dates + disclosed reach/spend, per network |
| product | tiktokshop, ebay, marketplace | `id · title · url · image · price.{amount,formatted,currency} · rating` |

A typical `author`:

**Example author**

```
{
  "id": "6659752019493208069",
  "handle": "stoolpresidente",
  "name": "Dave Portnoy",
  "url": "https://www.tiktok.com/@stoolpresidente",
  "followers": 4400000,
  "verified": true,
  "avatar_url": "https://…"
}
```

## Full-profile bundles are bounded pages

Supported social full-profile bundles return `profile`, a source-defined page of `posts`, and `posts_pagination`. The requested `posts` value is a desired page size, not a promise of that many records. A successful page may be shorter or longer. Follow `posts_pagination.next_params` with all its returned parameters; do not assume a `data.cursor` field. YouTube's channel bundle instead returns `recent_videos`, `cursor` and `recent_videos_pagination`.

Inspect `complete`, `partial` and `legs` where supplied. HTTP 200 can contain a partial bundle. `complete: true` means the requested components and bounded page succeeded, not that the account's entire history was collected. Missing continuation can mean unsupported or unknown pagination, not an empty history.

## Completeness and warnings

`data._warnings` collects reported component failures, nested limitations and computed-value bounds. Warnings do not change `success` to false. The envelope also carries `_completeness.state`: `partial` for detected omissions, `complete` when the source explicitly confirms its requested components, and `unknown` otherwise. Absence of a warning does not prove that the platform supplied every field or its entire history. Large results can report `inspection_limited: true`. Array payloads carry warnings on the envelope.

`GET /v1/status` is a free authenticated endpoint. Its additive `health`field reports `operational`, `degraded`, `down` or `unknown` from current circuits and recent request evidence. The older `state` field retains its traffic-window meaning. `updated_at`identifies the snapshot; it is reused for up to ten seconds. Source version identifiers are not uniformly reported, so `upstream_versions` remains null; normalization revisions are reported separately.

## Computed fields and honest nulls

Source fields and arithmetic are distinct from model-generated interpretations. Where supported, formulas, sample sizes, receipts and warnings describe how derived figures were produced. Full-profile `computed` fields are arithmetic over the returned page, not an AI analysis. Optional model-derived outputs are interpretations, not source facts.`youtube/video-sponsors` is inferential; absence of a detected sponsor does not prove there was none.

Missing fields may be absent or `null`, depending on the endpoint; neither means zero or false. Source-reported zero remains zero. A transcript endpoint can return `transcript: null, has_transcript: false` after checking for captions; that successful check costs zero credits. Inspect warnings and completeness metadata. A fallback can provide fewer fields or support different filters and pagination; unsupported controls may return an error instead of silently running a different query.

## Versioning

How `/v1` evolves — additive fields only, breaking changes on a new version path, and the deprecation notice with its headers — is on [Versioning & deprecation](https://www.monocrawl.com/docs/versioning).
