npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@qzsy/ozon-seller-premium

v0.2.1

Published

Bun-only TypeScript client for selected Ozon Seller read-only endpoints

Readme

@qzsy/ozon-seller-premium

Bun-only、TypeScript、零运行时依赖的 Ozon Seller 选定只读接口客户端。

安全与合规

这是非官方内部只读 API 客户端,不代表 Ozon,接口可能随时变化。

  • Cookie 为高敏感凭据:只用合法授权会话,勿写入仓库、日志、Issue 或聊天
  • SDK 不会自动登录,不处理验证码 / 2FA,不持久化 Cookie 或响应
  • 不提供结算报表导出、文件上传下载、评价回复等写操作或未覆盖能力
  • 使用本软件即自行承担授权、合规与接口变化风险(MIT)

安装

bun add @qzsy/ozon-seller-premium

仅支持 Bun;使用原生 fetch(可注入自定义实现)。

快速开始

import { OzonSellerClient } from "@qzsy/ozon-seller-premium";

const client = new OzonSellerClient({
  cookie: Bun.env.OZON_SELLER_COOKIE ?? "",
  companyId: Number(Bun.env.OZON_COMPANY_ID),
});

const premium = await client.account.getPremiumStatus(
  Number(Bun.env.OZON_COMPANY_ID),
);

建议用环境变量注入凭据,不要在代码里硬编码 Cookie。

客户端配置

new OzonSellerClient({
  cookie: string;       // 必填:卖家后台会话 Cookie
  companyId: number;    // 必填:整数公司 ID
  baseUrl?: string;     // 默认 https://seller.ozon.ru
  language?: string;    // 默认 ru-RU
  pageType?: string;    // 默认 "",部分页面接口可能依赖
  timeoutMs?: number;   // 默认 15000
  fetch?: typeof fetch; // 可选:测试或自定义 HTTP
});

API 一览

挂载点:client.account · client.redemptions · client.analytics · client.products · client.company · client.chat · client.notice · client.files · client.poll · client.resolve · client.composer

账户 client.account

| 方法 | 说明 | | --- | --- | | getRoles() | 当前账号角色列表 | | getPremiumStatus(companyId) | 指定公司的 Premium 订阅状态 | | getAnalyticsPremiumStatus() | 分析侧 Premium 状态 | | getInterfaceState() | 用户界面状态(已解析为对象) |

const roles = await client.account.getRoles();
const ui = await client.account.getInterfaceState();

回购分析 client.redemptions

| 方法 | 说明 | | --- | --- | | getLevels() | 回购水平分档(low / medium / high) | | getReasons() | 未回购原因 | | listGoods(limit?, offset?) | 商品回购列表;默认 limit=7offset=0limit 1..1000 | | getPriceSegments() | 价格段分布 | | getDynamics() | 近四周动态明细(固定 FourWeeks) | | getDynamicsTotal() | 近四周动态汇总(固定 FourWeeks) | | getTopSkuReasons() | Top SKU 未回购原因 | | getSoldCategoryTree() | 已售类目树;返回 CategoryTreeResponse,可用 flattenSoldCategoryTree() 展平 | | getDashboard() | 并行拉取上述指标(不含 listGoods),任一失败即整体失败 |

const dash = await client.redemptions.getDashboard();
const goods = await client.redemptions.listGoods(20, 0);

图表指标 client.analytics

对应卖家后台「分析 → 图表 → 所有指标」。

import { ANALYTICS_TABLE_METRICS } from "@qzsy/ozon-seller-premium";

const data = await client.analytics.getData({
  dateFrom: "2026-07-01",
  dateTo: "2026-07-14",
  metrics: [...ANALYTICS_TABLE_METRICS], // 长度 1..14
  dimensions: ["sku"],                   // 可选,默认 ["sku"]
  limit: 100,                            // 可选,1..1000,默认 100
  offset: 0,                             // 可选,默认 0
  // filters / sort / nameLike / timezone / isGeo / isAction
});

| 约束 | 说明 | | --- | --- | | metrics | 必填,非空,最多 14 个;未知指标可能被上游静默丢弃 | | ANALYTICS_TABLE_METRICS | 预置常用表指标集(已 ≤ 14) | | 常用维度 | skudayweekmonthbrandcategory1… |

完整指标 / 维度枚举见包内类型 AnalyticsMetricAnalyticsDimensionId

商品 client.products

| 方法 | 说明 | | --- | --- | | listByFilter(query?) | 单页列表;按 parts 拉取分片 | | listAll(query?, maxPages?) | 游标翻页聚合;默认最多 20 页(1..100) | | listRatingsIndex(options?) | 拉取含评级的商品,返回 Map(键为 sku / offerId) |

// 单页:基础信息 + SKU 来源 + 评级
const page = await client.products.listByFilter({
  parts: ["PART_ITEM", "PART_SOURCE", "PART_RATING"],
  search: "",
  limit: 100,
});

// 多页
const all = await client.products.listAll(
  { parts: ["PART_ITEM", "PART_SOURCE"], limit: 100 },
  10,
);

// SKU / offer_id → 星级摘要
const ratings = await client.products.listRatingsIndex({ maxPages: 8 });
const one = ratings.get("123456789");

常用 partsPART_ITEMPART_SOURCEPART_RATINGPART_PRICEPART_STOCKSPART_STATUSESPART_MEDIA 等。未请求的分片不会出现在响应中。

listByFilter 还可传 visibilitysortBysortDircursorfilters 等,详见类型 ProductListByFilterQuery

公司 client.company

| 方法 | 说明 | | --- | --- | | getFinanceInfo(companyId?) | 法人 / 税号 / 合同列表;默认使用客户端 companyId |

const finance = await client.company.getFinanceInfo();
console.log(finance.result.legal_name, finance.result.contracts.length);

聊天 client.chat

| 方法 | 说明 | | --- | --- | | getGroupsUnreadCount(companyMode?) | 分组未读数;main 为数字字符串;默认 companyMode=seller |

通知 client.notice

| 方法 | 说明 | | --- | --- | | list(companyId?) | 通知列表;无通知时 result 为空数组 |

文件桶 client.files

| 方法 | 说明 | | --- | --- | | getBuckets() | 只读存储桶名列表(无上传 / 下载) |

问卷 client.poll

| 方法 | 说明 | | --- | --- | | getActual({ companyId?, pollType? }) | 当前有效问卷;默认 pollType=NPS;无问卷时返回 {} |

可用 hasActivePoll(res) 判断是否存在 company_poll_id

路由 Resolve client.resolve

| 方法 | 说明 | | --- | --- | | resolve(route, trigger?, sellerId?) | 页面加载 / 闲置触发的 resolve;默认 onPageLoad |

await client.resolve.resolve("/app/analytics/redemptions", "onPageLoad");

Composer client.composer

| 方法 | 说明 | | --- | --- | | getPage({ url }) | 拉取页面 layout / widgetStates / userInfo 等 | | getWidget({ asyncData }) | 按 layout 的 asyncData 拉取 widget | | parseWidgetState(page, stateId?) | 二次解析 widgetStates JSON | | parseMenuContent(page, stateId?) | 解析侧栏菜单 content |

const page = await client.composer.getPage({
  url: "/app/dashboard/main/menu?path_hint=%2Fapp%2Fanalytics%2Fredemptions&companyMode=seller",
});
const menu = client.composer.parseMenuContent(page);

错误处理

失败时抛出 OzonSellerError(或其子类 ContractError):

| code | 含义 | | --- | --- | | HTTP_ERROR | 非 2xx;可读 error.status | | INVALID_JSON | 响应不是合法 JSON | | TIMEOUT | 超过 timeoutMs | | NETWORK_ERROR | 其它网络失败 | | CONTRACT_ERROR | 响应形状不符合预期契约 |

部分错误带有 traceId(来自响应头 X-O3-Trace-Id)。错误消息不会包含 Cookie 或完整请求头。

import { OzonSellerError, ContractError } from "@qzsy/ozon-seller-premium";

try {
  await client.analytics.getData({ /* ... */ });
} catch (e) {
  if (e instanceof ContractError) {
    // 形状校验失败
  } else if (e instanceof OzonSellerError) {
    console.error(e.code, e.status, e.traceId);
  }
}

能力范围

| 已提供 | 未提供 | | --- | --- | | 角色 / Premium / 界面状态 | 结算报表导出、账期明细流水 | | 回购 levels / reasons / 动态 / 类目树等 | 文件上传 / 下载(仅桶列表) | | 图表 data/v1(metrics ≤ 14) | xapi 遥测埋点 | | 商品 list-by-filter(含评级分片) | 评价回复等写操作 | | 公司 finance-info(法人 / 合同) | | | 聊天未读 / 通知列表 / NPS poll | | | 路由 resolve / Composer page+widget | |

HAR 中 seller.ozon.ru 业务接口均已覆盖;xapi.ozon.ru 埋点不在范围内。

响应只做轻量运行时检查;字段以 TypeScript 类型为准,上游变更时类型与行为可能需要同步更新。

License

MIT