> **For coding agents and LLMs:** This is one published Social Fetch blog post (markdown export). Product docs and API orientation live in [`/llms.txt`](https://www.socialfetch.dev/llms.txt). The HTML article is at the on-site URL below.

## This page

- **On-site (HTML):** [https://www.socialfetch.dev/blog/the-envelope-is-the-product](https://www.socialfetch.dev/blog/the-envelope-is-the-product)
- **Markdown (.mdx) URL:** [https://www.socialfetch.dev/blog/the-envelope-is-the-product.mdx](https://www.socialfetch.dev/blog/the-envelope-is-the-product.mdx)
- **Blog:** [https://www.socialfetch.dev/blog](https://www.socialfetch.dev/blog)

---

# The envelope is the product (API design)

When you evaluate a new API, the demo sells you on the payload: the parsed TikTok post, the YouTube transcript, the nested creator profile. In production, you spend most of your time on the envelope, the wrapper around that payload.

The envelope is the `meta` object with your request ID, credit usage, and API version. It is the typed error body that mirrors the happy path. It is what keeps a pipeline running for a year instead of paging you at 2 a.m. when upstream HTML shifts.

## The quiet contract of API design

Raw platform JSON mirrors whatever a social network shipped last Tuesday. Your app should not have to reverse-engineer field renames to learn what happened.

A quiet contract is boring on purpose: the same top-level shape on success and failure, one place to read `requestId` and what the call cost, and errors you can branch on instead of scraping HTML to guess the failure mode.

That predictability is the gap between "we wired up an Instagram integration" and "we can run this job every night without babysitting parsers."

## What a production API envelope carries

A good envelope answers four questions without opening a support thread: which request was this, what did it cost, what broke, and which API version answered.

On Social Fetch, successful responses pair `data` with `meta`. The `meta` object carries `requestId`, `creditsCharged` on metered routes, and `version`. Errors use the same `{ error }` envelope shape documented in [Errors](/docs/errors), so handler logic stays in one code path.

Example metered call, using the same `x-api-key` header from the [Quickstart](/docs/quickstart):

`GET https://api.socialfetch.dev/v1/tiktok/profiles/charlidamelio`

(`data` is trimmed for readability. Log and paste `meta` into support tickets.)

```json
{
  "data": {
    "lookupStatus": "found",
    "profile": {
      "platform": "tiktok",
      "handle": "charlidamelio",
      "displayName": "charli d'amelio",
      "verified": true,
      "profileUrl": "https://www.tiktok.com/@charlidamelio"
    },
    "metrics": {
      "followers": 157118150,
      "following": 1370,
      "likes": 12065883466,
      "posts": 3056
    }
  },
  "meta": {
    "requestId": "req_07d1da65-c0ca-4482-820a-15f1b266eede_pg_1170a59e",
    "creditsCharged": 1,
    "version": "v1"
  }
}
```

Follower counts above illustrate response shape, not a live scrape from this article's publish date. Branch on `data.lookupStatus` before you write rows.

## Credits bill on completed lookups

Metered routes charge when a lookup completes, as documented per endpoint. That includes HTTP `200` outcomes like `not_found` or `private` where the body still carries a `lookupStatus`. Pre-send validation errors, `lookup_failed`, and `503 temporarily_unavailable` do not bill the same way.

Reconcile your ledger against `meta.creditsCharged`, not your request count. Per-route costs live in the [API reference](/docs/api). Full billing rules: [Credits](/docs/credits).

## API debuggability in production

The envelope turns "something in the app broke" into a bounded incident. You get one `requestId` to log and paste, not a user trying to explain which button they clicked.

Log `meta.requestId` on every call, success or failure. Surface it in internal logs or your own error UI when you re-wrap responses. That is how you trace a Tuesday pipeline miss without guessing proxy health.

## Why social data APIs need this more

Social platforms change HTML layouts, rate limits, and edge cases on their own schedule. Your fetch layer will fail in ways outside your control.

When that happens, you need honest domain data when the fetch works and honest operational data when it does not. The envelope is where the operational data lives. It moves connection maintenance off your team and onto the API provider.

## Where to go next

Start with the [Quickstart](/docs/quickstart) for auth headers and a free `GET /v1/whoami` smoke test. Keep [Errors](/docs/errors) open while you wire retry logic. Plan volume from `meta.creditsCharged` on [Pricing](/pricing).
