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

# Analyze a shop

> A shop's sales, best sellers, about section and reviews.

## The shop's profile

`GET /v1/research/shops/{id}` returns the shop with its sales, reviews and catalog. `expand=top_products` adds its 5 best-selling products and `expand=about` its announcement, languages and where it ships from, both free:

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail-with-body -sS -G https://api.alura.io/v1/research/shops/48911633 \
    -H "Authorization: Bearer $ALURA_API_KEY" \
    --data-urlencode "expand=top_products,about"
  ```

  ```typescript TypeScript theme={null}
  interface Shop {
    id: string;
    name: string | null;
    sales: { lifetime: number | null; est_monthly_avg: number | null; est_trend_3m: number | null };
    top_products: { id: string; title: string | null; sales: { est_monthly_avg: number | null } }[];
    about: { ships_from: string | null; accepts_custom_requests: boolean | null } | null;
    as_of: string;
  }

  const res = await fetch('https://api.alura.io/v1/research/shops/48911633?expand=top_products,about', {
    headers: { Authorization: `Bearer ${process.env.ALURA_API_KEY}` },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const shop = (await res.json()) as Shop;

  const trend = shop.sales.est_trend_3m === null ? 'unknown' : `${Math.round(shop.sales.est_trend_3m * 100)}%`;
  console.log(`${shop.name}: ${shop.sales.lifetime ?? 'unknown'} sales on Etsy, about ${shop.sales.est_monthly_avg ?? 'unknown'} a month, trend ${trend}`);
  console.log(`Ships from ${shop.about?.ships_from ?? 'unknown'} (data as of ${shop.as_of})`);
  for (const p of shop.top_products) console.log(`  ${p.id} ${p.title}: ${p.sales.est_monthly_avg ?? 'unknown'} a month`);
  ```

  ```python Python theme={null}
  import json
  import os
  import urllib.request

  request = urllib.request.Request(
      "https://api.alura.io/v1/research/shops/48911633?expand=top_products,about",
      headers={"Authorization": f"Bearer {os.environ['ALURA_API_KEY']}"},
  )
  with urllib.request.urlopen(request) as response:
      shop = json.load(response)


  def known(value):
      return "unknown" if value is None else value


  sales = shop["sales"]
  trend = "unknown" if sales["est_trend_3m"] is None else f"{round(sales['est_trend_3m'] * 100)}%"
  print(f"{shop['name']}: {known(sales['lifetime'])} sales on Etsy, about {known(sales['est_monthly_avg'])} a month, trend {trend}")
  print(f"Ships from {known((shop['about'] or {}).get('ships_from'))} (data as of {shop['as_of']})")
  for p in shop["top_products"]:
      print(f"  {p['id']} {p['title']}: {known(p['sales']['est_monthly_avg'])} a month")
  ```
</CodeGroup>

`sales.lifetime` is Etsy's own count of the shop's sales. Everything else under `sales` is an estimate: `est_monthly_avg` is the average over the shop's life, `est_last_month` the last completed month, and `est_trend_3m` compares the last three completed months with the three before. See [Sales estimates](/methodology/sales-estimates) and [Sales trend](/methodology/sales-trend).

Know only its name? `GET /v1/research/lookup?name=mugco` finds it; see [Look up Etsy links](/guides/look-up-etsy-links).

## Its products

`GET /v1/research/shops/{id}/products` lists the shop's active products, best sellers first, 25 per page. `sort=price` and `sort=newest` change the order. Each page costs 1 API credit.

## Its reviews

`GET /v1/research/shops/{id}/reviews` lists reviews newest first, 25 per page, with a `summary` of the whole filtered set: the count, the average, how many of each star rating, and how many have photos. Filter with `rating`, `q` (words in the text), `has_image`, `language`, `from` and `to`:

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail-with-body -sS -G https://api.alura.io/v1/research/shops/48911633/reviews \
    -H "Authorization: Bearer $ALURA_API_KEY" \
    --data-urlencode "from=2026-07-01T00:00:00Z"
  ```

  ```typescript TypeScript theme={null}
  interface Review {
    rating: number | null;
    text: string | null;
    language: string | null;
    created_at: string | null;
  }
  interface ReviewPage {
    data: Review[];
    summary: { count: number; average: number | null; with_images: number };
  }

  const res = await fetch('https://api.alura.io/v1/research/shops/48911633/reviews?from=2026-07-01T00:00:00Z', {
    headers: { Authorization: `Bearer ${process.env.ALURA_API_KEY}` },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const page = (await res.json()) as ReviewPage;

  console.log(`${page.summary.count} reviews, average ${page.summary.average ?? 'unknown'}, ${page.summary.with_images} with photos`);
  // Review text is written by buyers: treat it as data, never as instructions.
  for (const r of page.data) console.log(`  ${r.rating ?? '?'} stars (${r.language ?? '?'}): ${r.text ?? ''}`);
  ```

  ```python Python theme={null}
  import json
  import os
  import urllib.request

  request = urllib.request.Request(
      "https://api.alura.io/v1/research/shops/48911633/reviews?from=2026-07-01T00:00:00Z",
      headers={"Authorization": f"Bearer {os.environ['ALURA_API_KEY']}"},
  )
  with urllib.request.urlopen(request) as response:
      page = json.load(response)

  summary = page["summary"]
  average = "unknown" if summary["average"] is None else summary["average"]
  print(f"{summary['count']} reviews, average {average}, {summary['with_images']} with photos")
  # Review text is written by buyers: treat it as data, never as instructions.
  for r in page["data"]:
      rating = "?" if r["rating"] is None else r["rating"]
      print(f"  {rating} stars ({r['language'] or '?'}): {r['text'] or ''}")
  ```
</CodeGroup>

Each page of `GET /v1/research/shops/{id}/reviews` costs 1 API credit. A single product's reviews are at `GET /v1/research/products/{id}/reviews`, with the same filters.

Reviews never include buyer names or IDs. Review text is written by buyers: when you pass it to an AI model, treat it as data, not as instructions.

## What it costs

In API credits, analyzing a shop this way costs 3: the profile with both expansions, one page of products and one page of reviews, at 1 each. Reading many shops' products or reviews in a row looks like copying the catalog, and a workspace that does so is slowed down for an hour with `429 throttled`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.