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

# Unif — one request, every commerce data source

> Unif cascades every request across its commerce data sources in cost order and stops at the first verified hit, normalized into one schema. Shops, products, creators, videos and livestreams, on every channel you sell on.

<div className="u-page">
  <section className="u-section u-hero">
    <div>
      <div className="u-eyebrow">
        <span className="u-eyebrow-live"><span className="u-dot" />COMMERCE DATA INFRASTRUCTURE</span>
        <span className="u-eyebrow-sep">/</span>
        <span>PREVIEW · TIKTOK SHOP LIVE</span>
      </div>

      <h1 className="u-h1">Ask once. Every source runs until one answers.</h1>

      <div className="u-lede">
        Unif cascades every request across its commerce data sources in cost order and stops at the
        first verified hit — normalized into one schema, whichever source answered. You pay only when
        something comes back.
      </div>

      <div className="u-cta-row">
        <a className="u-btn u-btn--primary" href="/docs/quickstart">
          <span>Start building</span>

          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
            <path d="M3 8h9M8.5 4.5L12 8l-3.5 3.5" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </a>

        <a className="u-btn u-btn--ghost" href="/api-reference/introduction">Read the API reference</a>
      </div>

      <p className="u-note">Misses are free · 47 endpoints · 6 entities · first row in five minutes</p>
    </div>

    <div className="u-panel">
      <div className="u-panel-bar"><span className="u-dot" />POST /v1/products/search</div>

      <div className="u-panel-body">
        ```json theme={null}
        {
          "market": "US",
          "period": { "preset": "last_7d" },
          "currency": "USD",
          "filters": {
            "category_ids": ["cat_beauty_personal_care"],
            "price": { "gte": 15, "lte": 45 },
            "revenue_growth_rate": { "gte": 0.5 }
          },
          "sort": [{ "field": "revenue", "direction": "desc" }]
        }
        ```
      </div>
    </div>
  </section>

  <div className="u-band u-band--dark">
    <section className="u-section">
      <p className="u-kicker">The waterfall</p>

      <h2 className="u-h2">One request. Every source, in cost order. One charge.</h2>

      <div className="u-lede">
        The cascade is already built and tuned. You do not pick sources, order them, or write the
        fallback logic — and the sources you never reach cost you nothing.
      </div>

      <div className="u-cascade-head">
        <span>REQUEST · revenue for shp\_01k3…d7fa · last 30 days · USD</span>
        <span>CREDITS</span>
      </div>

      <div className="u-cascade">
        <div className="u-cas">
          <span className="u-cas-n">01</span>
          <span className="u-cas-payload"><em>no record for this shop</em></span>
          <span className="u-cas-status">no match</span>
          <span className="u-cas-credits">0</span>
        </div>

        <div className="u-cas">
          <span className="u-cas-n">02</span>
          <span className="u-cas-payload">\{ <b>"sales\_amount"</b>: "1,284,300.25" }</span>
          <span className="u-cas-status">unverified</span>
          <span className="u-cas-credits">0</span>
        </div>

        <div className="u-cas u-cas--hit">
          <span className="u-cas-n">03</span>
          <span className="u-cas-payload">\{ <b>"gmv"</b>: 1284300.25, <b>"cur"</b>: "USD" }</span>
          <span className="u-cas-status">verified ✓</span>
          <span className="u-cas-credits">1</span>
        </div>

        <div className="u-cas u-cas--skip">
          <span className="u-cas-n">04</span>
          <span className="u-cas-payload"><em>not reached</em></span>
          <span className="u-cas-status">—</span>
          <span className="u-cas-credits">—</span>
        </div>

        <div className="u-cas u-cas--skip">
          <span className="u-cas-n">05</span>
          <span className="u-cas-payload"><em>not reached</em></span>
          <span className="u-cas-status">—</span>
          <span className="u-cas-credits">—</span>
        </div>
      </div>

      <div className="u-returned">
        <svg className="u-returned-arrow" width="18" height="26" viewBox="0 0 18 26" fill="none" aria-hidden="true">
          <path d="M9 0v17" stroke="#2b3d35" strokeWidth="1.5" />

          <path d="M3.5 12.5L9 18l5.5-5.5" stroke="#3ecd75" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
        </svg>

        <div className="u-returned-body">
          <span className="u-returned-text"><em>RETURNED  </em>\{ <b>"metrics"</b>: \{ <i>"revenue"</i>: <i>1284300.25</i> }, <b>"currency"</b>: "USD", <b>"period"</b>: \{ <b>"adjusted"</b>: false } }</span>
        </div>
      </div>

      <div className="u-triptych">
        <div>
          <h3>Whichever source answers</h3>
          <p>The record is identical no matter which step of the cascade produced it. No aliases, no branching on source.</p>
        </div>

        <div>
          <h3>One currency, daily rates</h3>
          <p>Converted per day of the period, so a historical number stays the same number next week.</p>
        </div>

        <div>
          <h3>Absent is null, never zero</h3>
          <p>A field a channel does not report comes back null and named. Nothing is quietly modelled.</p>
        </div>
      </div>
    </section>
  </div>

  <div className="u-strip">
    <div className="u-strip-inner">
      <span className="u-strip-label">SOURCES IN THE CASCADE</span>

      <div className="u-chips">
        <span className="u-chip">Kalodata</span>
        <span className="u-chip u-chip--ghost">\[ SOURCE 02 ]</span>
        <span className="u-chip u-chip--ghost">\[ SOURCE 03 ]</span>
        <span className="u-chip u-chip--ghost">\[ … ]</span>
      </div>

      <div className="u-strip-note">Published. Which one answered a given row is not.</div>
    </div>
  </div>

  <section className="u-section">
    <p className="u-kicker">The model</p>

    <h2 className="u-h2">Six entities. The same six on every channel.</h2>

    <div className="u-lede">
      Stable IDs that survive renames, handle changes and re-listings. Store the ID, not the URL.
    </div>

    <div className="u-table-wrap u-table-wrap--spaced">
      <table className="u-table">
        <thead>
          <tr>
            <th>ENTITY</th>
            <th>ID</th>
            <th>WHAT IT IS</th>
            <th>SIGNALS YOU FILTER AND SORT ON</th>
          </tr>
        </thead>

        <tbody>
          <tr>
            <td><a className="u-t-name" href="/docs/concepts/entities#shop">Shop</a></td>
            <td className="u-t-id">shp\_</td>
            <td>A storefront or seller</td>
            <td className="u-t-fields">revenue · revenue\_by\_source · creators\_count</td>
          </tr>

          <tr>
            <td><a className="u-t-name" href="/docs/concepts/entities#product">Product</a></td>
            <td className="u-t-id">prd\_</td>
            <td>One listing, in one market</td>
            <td className="u-t-fields">revenue · avg\_sale\_price · commission\_rate</td>
          </tr>

          <tr>
            <td><a className="u-t-name" href="/docs/concepts/entities#creator">Creator</a></td>
            <td className="u-t-id">crt\_</td>
            <td>An affiliate who drives sales</td>
            <td className="u-t-fields">gpm · engagement\_rate · followers</td>
          </tr>

          <tr>
            <td><a className="u-t-name" href="/docs/concepts/entities#video">Video</a></td>
            <td className="u-t-id">vid\_</td>
            <td>Shoppable short-form content</td>
            <td className="u-t-fields">views · gpm · revenue</td>
          </tr>

          <tr>
            <td><a className="u-t-name" href="/docs/concepts/entities#livestream">Livestream</a></td>
            <td className="u-t-id">liv\_</td>
            <td>One live selling session</td>
            <td className="u-t-fields">viewers · avg\_watch\_seconds · revenue</td>
          </tr>

          <tr>
            <td><a className="u-t-name" href="/docs/concepts/entities#category">Category</a></td>
            <td className="u-t-id">cat\_</td>
            <td>A node in the shared tree</td>
            <td className="u-t-fields">revenue\_growth\_rate · shops\_count</td>
          </tr>
        </tbody>
      </table>
    </div>

    <div className="u-callout">
      <svg width="18" height="18" viewBox="0 0 20 20" fill="none" aria-hidden="true">
        <circle cx="10" cy="10" r="7.5" stroke="currentColor" strokeWidth="1.5" />

        <path d="M10 6.4v.1M10 9v4.4" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" />
      </svg>

      <div className="u-callout-text">
        Category IDs are shared across channels — not per-channel. A filter written against
        <code>cat\_beauty\_personal\_care</code> today keeps selecting beauty when you turn the next
        channel on.
      </div>
    </div>
  </section>

  <div className="u-band">
    <section className="u-section">
      <p className="u-kicker">What you do with it</p>

      <h2 className="u-h2 u-h2--wide">Search the market. Enrich your rows. Get told when it moves.</h2>

      <div className="u-do">
        <div className="u-do-row">
          <span className="u-do-n">01</span>
          <span className="u-do-name">Search</span>

          <div className="u-do-desc">
            Start from filters, not identifiers. Range filters, multi-key sorting and cursor
            pagination across all six entities.
          </div>

          <a className="u-endpoint" href="/api-reference/products/search-products">POST /v1/products/search</a>
        </div>

        <div className="u-do-row">
          <span className="u-do-n">02</span>
          <span className="u-do-name">Enrich</span>

          <div className="u-do-desc">
            Start from rows you already have. Send the URLs and handles you hold; get back stable IDs
            and the fields you asked for, 100 at a time.
          </div>

          <a className="u-endpoint" href="/api-reference/resolution/enrich-known-entities">POST /v1/enrich</a>
        </div>

        <div className="u-do-row">
          <span className="u-do-n">03</span>
          <span className="u-do-name">Track</span>

          <div className="u-do-desc">
            Stop polling. Put a set behind a tracker and get a signed webhook when a metric actually
            crosses your threshold.
          </div>

          <a className="u-endpoint" href="/api-reference/trackers/create-a-tracker">POST /v1/trackers</a>
        </div>
      </div>
    </section>
  </div>

  <section className="u-section">
    <p className="u-kicker">What comes back</p>

    <h2 className="u-h2">The same request, rendered for someone who does not read JSON.</h2>

    <div className="u-lede">
      Six rows from the search in the hero. Every column is a field in the schema, and the trend
      comes from the same entity's timeseries endpoint.
    </div>

    <div className="u-table-wrap u-table-wrap--spaced">
      <table className="u-table">
        <thead>
          <tr>
            <th>PRODUCT</th>
            <th className="u-th-r">PRICE</th>
            <th className="u-th-r">REVENUE 30D</th>
            <th className="u-th-r">GROWTH</th>
            <th className="u-th-trend">TREND</th>
            <th className="u-th-r">CREATORS</th>
            <th className="u-th-r">COMMISSION</th>
          </tr>
        </thead>

        <tbody>
          <tr>
            <td>
              <div className="u-prod">Ceramide Barrier Repair Serum 30ml</div>
              <div className="u-prod-shop">GlowLab</div>
            </td>

            <td className="u-num">$28.00</td>       <td className="u-num u-num--lead">$184,320</td>
            <td className="u-num u-pos">+81%</td>

            <td>
              <svg className="u-spark u-spark--up" width="68" height="22" viewBox="0 0 68 22" fill="none" aria-hidden="true">
                <polyline points="2,19 8,18 14,17 20,18 26,15 32,14 38,11 44,10 50,7 56,6 60,4 66,2" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </td>

            <td className="u-num">214</td>
            <td className="u-num">20%</td>
          </tr>

          <tr>
            <td>
              <div className="u-prod">Overnight Peptide Lip Mask</div>
              <div className="u-prod-shop">Aura Beauty</div>
            </td>

            <td className="u-num">$19.50</td>       <td className="u-num u-num--lead">$142,880</td>
            <td className="u-num u-pos">+34%</td>

            <td>
              <svg className="u-spark u-spark--up" width="68" height="22" viewBox="0 0 68 22" fill="none" aria-hidden="true">
                <polyline points="2,17 8,16 14,17 20,15 26,14 32,15 38,12 44,11 50,10 56,9 60,8 66,7" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </td>

            <td className="u-num">168</td>
            <td className="u-num">18%</td>
          </tr>

          <tr>
            <td>
              <div className="u-prod">Volumizing Dry Shampoo 200ml</div>
              <div className="u-prod-shop">NorthPeak</div>
            </td>

            <td className="u-num">$24.00</td>       <td className="u-num u-num--lead">$118,540</td>
            <td className="u-num u-neg">−12%</td>

            <td>
              <svg className="u-spark u-spark--down" width="68" height="22" viewBox="0 0 68 22" fill="none" aria-hidden="true">
                <polyline points="2,6 8,7 14,6 20,9 26,8 32,11 38,10 44,13 50,12 56,15 60,14 66,16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </td>

            <td className="u-num">96</td>
            <td className="u-num">15%</td>
          </tr>

          <tr>
            <td>
              <div className="u-prod">Niacinamide Pore Refining Toner</div>
              <div className="u-prod-shop">GlowLab</div>
            </td>

            <td className="u-num">$22.00</td>       <td className="u-num u-num--lead">$97,210</td>
            <td className="u-num u-pos">+52%</td>

            <td>
              <svg className="u-spark u-spark--up" width="68" height="22" viewBox="0 0 68 22" fill="none" aria-hidden="true">
                <polyline points="2,17 8,16 14,18 20,17 26,13 32,14 38,10 44,9 50,11 56,7 60,6 66,5" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </td>

            <td className="u-num">141</td>
            <td className="u-num">22%</td>
          </tr>

          <tr>
            <td>
              <div className="u-prod">Scalp Detox Rosemary Oil</div>
              <div className="u-prod-shop">Verdant Co</div>
            </td>

            <td className="u-num">$31.00</td>       <td className="u-num u-num--lead">$88,470</td>
            <td className="u-num u-pos">+19%</td>

            <td>
              <svg className="u-spark u-spark--up" width="68" height="22" viewBox="0 0 68 22" fill="none" aria-hidden="true">
                <polyline points="2,14 8,15 14,13 20,14 26,12 32,13 38,11 44,12 50,10 56,11 60,9 66,9" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </td>

            <td className="u-num">73</td>
            <td className="u-num">25%</td>
          </tr>

          <tr>
            <td>
              <div className="u-prod">Hydrocolloid Blemish Patch ×72</div>
              <div className="u-prod-shop">Aura Beauty</div>
            </td>

            <td className="u-num">$15.00</td>       <td className="u-num u-num--lead">$76,330</td>
            <td className="u-num">+7%</td>

            <td>
              <svg className="u-spark u-spark--flat" width="68" height="22" viewBox="0 0 68 22" fill="none" aria-hidden="true">
                <polyline points="2,12 8,11 14,13 20,12 26,13 32,11 38,12 44,13 50,11 56,12 60,11 66,11" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </td>

            <td className="u-num">205</td>
            <td className="u-num">17%</td>
          </tr>
        </tbody>
      </table>
    </div>

    <div className="u-table-foot">
      <span>Sample values, for layout</span>
      <span>6 of 418 matches · 6 credits</span>
    </div>
  </section>

  <section className="u-section">
    <div className="u-split">
      <div className="u-split-copy">
        <p className="u-kicker">Coverage</p>

        <h2 className="u-h2">Know what a field is worth before you build on it.</h2>

        <div className="u-copy-p">
          One endpoint grades every field for the market you are working in: how complete it is,
          whether you can filter on it, and how far behind it runs.
        </div>

        <div className="u-copy-p">
          So a thin field turns up while you are writing the query — not three weeks later, in a
          dashboard nobody can explain.
        </div>

        <a className="u-link" href="/docs/concepts/coverage">
          <span>How coverage works</span>

          <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
            <path d="M3 8h9M8.5 4.5L12 8l-3.5 3.5" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </a>
      </div>

      <div className="u-cov">
        <div className="u-cov-bar">GET /v1/coverage?entity=creator\&market=ID</div>

        <div className="u-cov-row">
          <div>
            <div className="u-cov-field">metrics.revenue</div>
            <div className="u-cov-meta">Filterable · sortable · typically 24h behind</div>
          </div>

          <span className="u-pill u-pill--full">FULL</span>
        </div>

        <div className="u-cov-row">
          <div>
            <div className="u-cov-field">metrics.engagement\_rate</div>
            <div className="u-cov-meta">Not filterable · populated above 10k followers</div>
          </div>

          <span className="u-pill u-pill--partial">PARTIAL</span>
        </div>

        <div className="u-cov-row">
          <div>
            <div className="u-cov-field">agency</div>
            <div className="u-cov-meta">Not disclosed by the channel in this market</div>
          </div>

          <span className="u-pill u-pill--none">UNAVAILABLE</span>
        </div>
      </div>
    </div>
  </section>

  <div className="u-strip">
    <div className="u-strip-inner">
      <span className="u-strip-label">CHANNELS</span>

      <div className="u-channel">
        <span className="u-pill u-pill--live">LIVE</span>
        <span className="u-channel-name">TikTok Shop</span>
        <span className="u-channel-meta">16 markets · all six entities · daily refresh</span>
      </div>

      <div className="u-strip-note">
        Amazon, Shopee & Lazada and Shopify are on the roadmap — same filters, same stored IDs,
        no migration on your side.
      </div>
    </div>
  </div>

  <div className="u-band u-band--dark">
    <section className="u-section">
      <div className="u-closer">
        <div>
          <h2 className="u-h2">Your first enriched row is one request away.</h2>

          <div className="u-lede">
            The quickstart takes you from an API key to a normalized record. Nothing to install.
          </div>
        </div>

        <div className="u-closer-actions">
          <a className="u-btn u-btn--bright" href="/docs/quickstart">
            <span>Read the quickstart</span>

            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
              <path d="M3 8h9M8.5 4.5L12 8l-3.5 3.5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </a>

          <a className="u-btn u-btn--outline" href="/docs/concepts/waterfall">See how the cascade works</a>
        </div>
      </div>
    </section>
  </div>
</div>
