Skip to main content
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

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

Cost order, not quality order

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.

Verification before return

A result that fails verification does not end the cascade. Step 02 returned a number and was still rejected, so step 03 ran.

Early exit

The first verified result wins. Steps 04 and 05 never execute, so they cannot cost you anything and cannot slow the request down.

One charge

You are billed for the hit, not for the attempts. See Credits.

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.

What you give up

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.

What you get back

No cascade to maintain. Source rosters, pricing and reliability all change underneath you, and none of it reaches your code.
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.
This is why the 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.

What the cascade does not fix

If every source in the cascade lacks a field for a market, running more of them changes nothing. That is what GET /coverage reports as unavailable, and the field comes back null.
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.
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.

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.
[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.
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.
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 and meta.refreshed_at instead.