Product Data (Structured vs Text)

const apiKey = process.env.WEBLINQ_API_KEY;
const base = 'https://api.weblinq.dev/v1';

export async function extractProduct(url) {
  // minimal but useful schema
  const schema = {
    type: 'object',
    properties: {
      name: { type: 'string' },
      price: { type: 'number' },
      currency: { type: 'string' },
      availability: { type: 'string' },
    },
    required: ['name', 'price', 'availability'],
  };

  const {
    data: { extracted },
  } = await post('/web/extract-json', {
    url,
    response_format: { type: 'json_schema', json_schema: schema },
  });

  return extracted;
}

function post(p, b) {
  return fetch(`${base}${p}`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(b),
  }).then((r) => r.json());
}

Competitor Store Snapshot

const apiKey = process.env.WEBLINQ_API_KEY;
const base = 'https://api.weblinq.dev/v1';

export async function snapshotStore(storeUrl) {
  // ① screenshot
  const shot = post('/web/screenshot', {
    url: storeUrl,
    screenshotOptions: { fullPage: true },
  });

  // ② internal links
  const links = post('/web/links', { url: storeUrl, includeExternal: false });

  // ③ quick store schema
  const schema = {
    type: 'object',
    properties: {
      storeName: { type: 'string' },
      totalProducts: { type: 'number' },
    },
  };

  const meta = post('/web/extract-json', {
    url: storeUrl,
    response_format: { type: 'json_schema', json_schema: schema },
    prompt: 'Store overview',
  });

  const [screenshot, linkData, storeInfo] = await Promise.all([
    shot,
    links,
    meta,
  ]);

  const productLinks = (linkData.data.links || [])
    .filter((l) => /\/(product|item|p)\//.test(l.url))
    .slice(0, 20);

  return {
    url: storeUrl,
    screenshot: screenshot.data.permanentUrl,
    storeInfo: storeInfo.data.extracted,
    productLinks,
  };
}

function post(p, b) {
  return fetch(`${base}${p}`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(b),
  }).then((r) => r.json());
}

Quick Price Report → PDF

const apiKey = process.env.WEBLINQ_API_KEY;
const base = 'https://api.weblinq.dev/v1';

export async function priceReport(urls) {
  const schema = {
    type: 'object',
    properties: {
      product: { type: 'string' },
      price: { type: 'number' },
      currency: { type: 'string' },
    },
    required: ['product', 'price', 'currency'],
  };

  const rows = await Promise.all(
    urls.map(async (url) => {
      const {
        data: { extracted },
      } = await post('/web/extract-json', {
        url,
        response_format: { type: 'json_schema', json_schema: schema },
      });
      return { url, ...extracted };
    }),
  );

  const html = `
    <html><body><h1>Price Report</h1>
    <table border="1">${rows
      .map(
        (r) => `
      <tr><td>${r.product}</td><td>${r.currency}${r.price}</td><td>${r.url}</td></tr>`,
      )
      .join('')}
    </table></body></html>`;

  const dataUri =
    'data:text/html;base64,' + Buffer.from(html).toString('base64');

  const {
    data: { permanentUrl },
  } = await post('/web/pdf', { url: dataUri });

  return { rows, pdf: permanentUrl };
}

function post(p, b) {
  /* helper like above */
}

Product Discovery (Multi-Shop)

const apiKey = process.env.WEBLINQ_API_KEY;
const base = 'https://api.weblinq.dev/v1';

export async function findProducts(query, limit = 10) {
  const {
    data: { results },
  } = await post('/web/search', {
    query: `${query} site:amazon.com OR site:ebay.com OR site:walmart.com`,
    limit,
  });

  const schema = {
    type: 'object',
    properties: {
      name: { type: 'string' },
      price: { type: 'number' },
      currency: { type: 'string' },
    },
  };

  const products = await Promise.all(
    results.map((r) =>
      post('/web/extract-json', {
        url: r.url,
        response_format: { type: 'json_schema', json_schema: schema },
      }).then((p) => ({
        platform: new URL(r.url).hostname,
        ...p.data.extracted,
      })),
    ),
  );

  return products.filter((p) => p.price).sort((a, b) => a.price - b.price);
}

function post(p, b) {
  /* helper */
}

Inventory Check (Stock Status)

const apiKey = process.env.WEBLINQ_API_KEY;
const base = 'https://api.weblinq.dev/v1';

export async function checkStock(urls) {
  const schema = {
    type: 'object',
    properties: {
      stockStatus: { type: 'string' },
      quantity: { type: 'number' },
    },
  };

  const items = await Promise.all(
    urls.map(async (url) => {
      const {
        data: { extracted },
      } = await post('/web/extract-json', {
        url,
        response_format: { type: 'json_schema', json_schema: schema },
        prompt: 'Current stock status',
      });
      return { url, ...extracted };
    }),
  );

  return {
    items,
    outOfStock: items.filter((i) => i.stockStatus === 'out_of_stock').length,
  };
}

function post(p, b) {
  /* helper */
}

Key Features

Always respect website terms of service and implement appropriate rate limiting when monitoring e-commerce sites.