> ## Documentation Index
> Fetch the complete documentation index at: https://unif.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The waterfall

> How one request becomes a cascade across sources, and what it costs.

No single source has every shop, every product or every creator. Coverage gaps are not a defect
of any one provider — they are the normal state of commerce data.

Unif answers a request by running a **cascade**: it queries sources in cost order, verifies each
result, and stops at the first one that passes. You get the coverage of the whole roster at
close to the cost of the cheapest source that happens to have the answer.

## What one request actually does

```
REQUEST   revenue for shp_01k3m9x7v2q8r4t6y0b1n5d7fa · last 30 days · USD

  01   no record for this shop            no match       0 credits
  02   { "sales_amount": "1,284,300.25" } unverified     0 credits
  03   { "gmv": 1284300.25, "cur": "USD" } verified ✓    1 credit
  04   —                                  not reached    —
  05   —                                  not reached    —

RETURNED  { "metrics": { "revenue": 1284300.25 }, "currency": "USD" }
```

Four things in that trace are worth naming, because each one is a promise:

<Steps>
  <Step title="Cost order, not quality order" icon="arrow-down-1-9">
    Sources are tried cheapest first. The order is tuned per entity, market and field — a source
    that is strong on US creators may sit late in the cascade for Indonesian shops.
  </Step>

  <Step title="Verification before return" icon="circle-check">
    A result that fails verification does not end the cascade. Step 02 returned a number and was
    still rejected, so step 03 ran.
  </Step>

  <Step title="Early exit" icon="forward-step">
    The first verified result wins. Steps 04 and 05 never execute, so they cannot cost you
    anything and cannot slow the request down.
  </Step>

  <Step title="One charge" icon="coins">
    You are billed for the hit, not for the attempts. See [Credits](/docs/platform/credits).
  </Step>
</Steps>

## Why you do not configure it

The cascade ships already built and tuned. There is no parameter to pick sources, reorder them,
set verification thresholds or write fallback logic — which is the point.

<CardGroup cols={2}>
  <Card title="What you give up" icon="lock">
    Control over the order. If you have a strong opinion about which source should answer for a
    given field, Unif is the wrong shape for you.
  </Card>

  <Card title="What you get back" icon="bolt">
    No cascade to maintain. Source rosters, pricing and reliability all change underneath you,
    and none of it reaches your code.
  </Card>
</CardGroup>

That trade is the product. Building the same coverage yourself means contracting with each
source, normalizing each payload, writing the fallback chain, and then re-tuning it every time
one of them changes its terms.

## Normalization is what makes it possible

A cascade only works if the steps are interchangeable. Step 02 called the field `sales_amount`
and step 03 called it `gmv`; one returned a formatted string, the other a number; one stated its
currency, the other did not.

Unif maps all of that to one schema **before** verification, which is why the returned record is
identical no matter which step produced it. Without normalization there is no cascade — only a
list of sources you would have to reconcile yourself.

<Note>
  This is why the [unified model](/docs/concepts/unified-model) is documented as a contract rather
  than a convenience. It is load-bearing: every guarantee in it is what lets a different source
  answer tomorrow without your code noticing.
</Note>

## What the cascade does not fix

<AccordionGroup>
  <Accordion title="A field no source reports" icon="ban">
    If every source in the cascade lacks a field for a market, running more of them changes
    nothing. That is what [`GET /coverage`](/docs/concepts/coverage) reports as `unavailable`,
    and the field comes back `null`.
  </Accordion>

  <Accordion title="An entity that does not exist" icon="circle-question">
    A dead listing or a mistyped handle exhausts the cascade and resolves `not_found`. Every step
    missed, so the request costs nothing. Retrying will not help.
  </Accordion>

  <Accordion title="Disagreement between sources" icon="code-compare">
    Two sources reporting the same shop rarely agree exactly. The cascade does not average them —
    it returns the first verified answer and tells you when it was refreshed. Reconciling
    competing numbers is a decision, and Unif does not make it silently on your behalf.
  </Accordion>
</AccordionGroup>

## Which sources are in it

Unif does not hide its roster. The sources behind a channel are published, and the first
TikTok Shop source is [Kalodata](https://www.kalodata.com).

<Info>
  **\[PLACEHOLDER — full source roster]** The complete list per channel, and the count, belong here
  once the roster is settled. Naming the roster is the strongest available evidence for a coverage
  claim, so this should not stay a placeholder for long.
</Info>

What is deliberately *not* in the API is **which source answered a given row**. A response tells
you how fresh and how complete a record is, not which step produced it — so that re-tuning the
cascade is never a breaking change for you.

<Warning>
  Do not build logic that depends on a particular source answering. Source order, membership and
  per-field strength all change over time, by design. Build against
  [coverage](/docs/concepts/coverage) and `meta.refreshed_at` instead.
</Warning>
