# Provenance (/docs/provenance)



LinkFetch ships provenance on every response. It's not a feature — it's
the contract. If you can't explain where your data came from, you can't
ship agent workflows to a regulated customer. We give you the audit
trail by default.

## The `meta.provenance` object [#the-metaprovenance-object]

Every endpoint response has this shape:

```json
{
  "data": { "...": "..." },
  "meta": {
    "request_id": "req_2Yq7zR1tDkH",
    "credits_charged": 5,
    "provenance": {
      "source": "extension",
      "fetched_at": "2026-04-23T14:02:11Z",
      "freshness_days": 6
    }
  }
}
```

### `source` [#source]

Which pipeline produced the row.

| Source      | Meaning                                                                                                                                   |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `extension` | Captured through the end user's own LinkedIn session via the [LinkFetch Chrome extension](/docs/extension). User is principal.            |
| `scraper`   | Public-page scrape (Jobs dataset). No login involved — only what a logged-out visitor sees on `/jobs/view/<id>` and the public guest API. |
| `cache`     | Served from LinkFetch's cache. Original source is preserved in `cache_origin`.                                                            |

### `fetched_at` [#fetched_at]

ISO-8601 timestamp (UTC) of when the underlying record was captured.
For cached rows this is the **original capture time**, not the cache
hit time — so freshness math works the same on a cold and a warm read.

### `freshness_days` [#freshness_days]

Integer: how many days have passed since `fetched_at`. Zero means
fetched today. Your agent can decide whether to re-fetch.

## Freshness policy [#freshness-policy]

LinkFetch caches responses per surface:

| Surface                         | Default TTL | Re-fetch on miss               |
| ------------------------------- | ----------- | ------------------------------ |
| `/v1/profiles`                  | 30 days     | Through the end user's session |
| `/v1/companies/:slug`           | 14 days     | Same                           |
| `/v1/companies/:slug/employees` | 14 days     | Same                           |
| `/v1/posts/:id`                 | 7 days      | Same                           |
| `/v1/jobs`                      | 1 hour      | Index refresh continuous       |
| `/v1/locations`                 | 30 days     | LinkedIn typeahead             |

You can override with `?fresh=true` to force a refetch. That charges
full credits; cache hits charge full credits too — see
[Pricing](/docs/pricing) for why.

## Audit trail [#audit-trail]

Every request is logged with:

* `request_id` returned in the response + `X-Request-Id` header
* Endpoint, params, status, duration, credits charged
* Which key was used
* Which source served the data

Accessible in the [dashboard usage page](/usage) or via a dedicated
audit export (email [info@linkfetch.io](mailto:info@linkfetch.io) for
the audit endpoint).

## Why we do it this way [#why-we-do-it-this-way]

The alternative — opaque data with no source stamp — is how every major
LinkedIn vendor before us operated. It's also why their compliance
stories collapsed under enforcement. Provenance is cheap; pretending
you don't have to care is expensive.

For the formal compliance posture see [Compliance](/docs/compliance).
