Litlyx API 使用详解
Litlyx 0.0.19 两套 API 实测详解:producer 采集端点(/event /visit /keep_alive,无认证+Shields 防护)与 dashboard 管理 API(会话登录/项目列表/统计/实时在线),请求字段表、实测响应回显、错误码与静默丢弃行为全记录。
Litlyx API 使用详解
目标:讲清 Litlyx 0.0.19 的两套 API——producer 数据采集 API(
/event、/visit、/keep_alive,无认证公开端点)与 dashboard 管理 API(登录会话 + 项目/统计接口),全部请求与响应均在本站五容器自托管栈上逐条 curl 实测,响应为实测回显。
一、环境信息
- 操作系统:Ubuntu(x86_64);Docker 27 + Compose v2,五服务栈(部署见 《Litlyx Docker Compose 部署指南》)
- Litlyx 版本:0.0.19(官方
litlyx/*:latest镜像) - API 端点分布:
- 采集 API:producer 服务,容器内 3001,宿主机映射
http://localhost:8135; - 管理 API:dashboard 服务(Nuxt 3/Nitro),容器内 3000,宿主机映射
http://localhost:8134,路由前缀/api;
- 采集 API:producer 服务,容器内 3001,宿主机映射
- 测试项目:
Doc Demo Site,项目 ID(pid)实测值6ae4267da0064c0b9a6c9546; - 客户端工具:curl 8.x;管理员账号
admin@litlyx.local(自托管引导账号)。
二、前置条件
- 五服务栈运行中,dashboard 日志出现
[SELFHOSTED] Admin account OK、consumer 日志出现Start reading loop; - 已登录 dashboard 创建项目并取得
pid(项目详情页可见,或查 Mongoprojects集合_id); - curl 与 jq 可用;
- 明确两类端点的认证差异(见下一节),避免用管理 API 的会话去调采集端点(不需要)。
三、API 总览
| 域 | 协议/形态 | 认证方式 | 端点 |
|---|---|---|---|
| 数据采集(producer) | HTTP POST + JSON,请求/响应极简(无 body 成功响应) | 无认证(防滥用靠内置 Shields:IP 黑名单、600+ Bot UA 模式、域名白名单) | POST /event、POST /visit、POST /keep_alive;兼容旧版 POST /v1/metrics/push、POST /v1/keep_alive |
| 管理(dashboard) | HTTP + JSON,Nitro 服务端路由 | nuxt-session Cookie(登录后下发,HttpOnly,7 天有效) | POST /api/auth/login、GET /api/project/list、GET /api/project/stats、GET /api/project/live_users 等 |
请求处理约定(源码口径,实测验证):
- 采集端点接收 JSON body 后不直接落库,而是压入 Redis Stream(
LITLYX_STREAM),由 consumer 异步消费解析——因此 producer 返回 200 只代表消息入队成功,不代表落库成功; - 请求体大小限制 25KB;
- 成功响应为空 body 的
200;被 Shields 拦截(IP 黑名单/Bot UA/域名不在白名单)返回400空响应; - 访客 IP 取请求头
X-Real-IP或X-Forwarded-For(按序),都缺省记0.0.0.0——反代场景必须转发该头; - 会话标识由服务端计算:
MD5(当日日期(it-IT 格式) + website + IP + userAgent),原始 IP 不落库(隐私设计)。
四、认证与首次调用
4.1 管理端登录(实测)
$ curl -s -D - -o /dev/null -X POST http://localhost:8134/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@litlyx.local","password":"Q1w2E3r4T!"}'
HTTP/1.1 204 No Content
set-cookie: nuxt-session=Fe26.2**8b3bf6ff73b58945f8f905866aeca3b49222f80efd3cb0529f1f39add9006504*VylOabCFzJ81YQF*…; Path=/; Expires=Fri, 06 Nov 2026 06:43:45 GMT; HttpOnly; Secure; SameSite=Lax
- 成功:
204 No Content+nuxt-sessionCookie(Fe26.2**前缀为 @hapi/iron 加密格式); - 失败:
400,响应体{"statusCode":400,"message":"Email or Password wrong"}; - 后续管理 API 全部用
-b cookies.txt携带 Cookie(curl-c保存、-b回放)。
4.2 采集端首次调用(无需登录,实测)
$ curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:8135/event \
-H 'Content-Type: application/json' \
-d '{"pid":"6ae4267da0064c0b9a6c9546","website":"doc-demo.example.com","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/126.0 Safari/537.36","name":"testEvent1","metadata":"{\"test\":\"something\"}"}'
200
五、数据采集 API 详解(producer)
5.1 POST /event(自定义事件)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
pid | string | ✅ | 项目 ID |
name | string | ✅(consumer 落库校验) | 事件名,如 click_on_buy_item |
website | string | ✅ | 触发站点域名 |
userAgent | string | ✅ | 访客 UA(服务端解析浏览器/OS/设备) |
metadata | string | 可选 | JSON 字符串(非对象),如 "{\"price\":\"1.50\"}" |
实测(含响应回显与落库验证):
$ curl -s -o /dev/null -w 'event:%{http_code}\n' -X POST http://localhost:8135/event \
-H 'Content-Type: application/json' \
-d '{"pid":"6ae4267da0064c0b9a6c9546","website":"doc-demo.example.com","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/126.0 Safari/537.36","name":"click_download","metadata":"{}"}'
event:200
落库结果(MongoDB events 集合实测回显,session/flowHash 为服务端计算的匿名哈希):
{
"_id": ObjectId('6ae43d03e2dcaafdd48a648e'),
"project_id": ObjectId('6ae4267da0064c0b9a6c9546'),
"name": "click_download",
"session": "676bde550d1b4aa71b51400ba82c95b1",
"flowHash": "efeb74ad83e1b42dd0ab77f67b1bb451",
"website": "doc-demo.example.com",
"created_at": ISODate('2026-10-30T06:45:23.576Z')
}
5.2 POST /visit(页面访问)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
pid / website / userAgent | string | ✅ | 同上 |
browser / os | string | ✅(consumer 落库校验) | 浏览器/操作系统名(官方 litlyx.js 自动填充;自编集成必须传) |
page | string | ✅(同上) | 页面路径 |
referrer | string | ✅(同上) | 来源(可为空字符串,不可缺字段) |
device | string | 可选 | 设备类型(desktop/mobile) |
screenWidth / screenHeight / language | string | 可选 | 一律字符串,数字类型触发 500(见 5.5) |
实测:
$ curl -s -o /dev/null -w 'visit:%{http_code}\n' -X POST http://localhost:8135/visit \
-H 'Content-Type: application/json' \
-d '{"pid":"6ae4267da0064c0b9a6c9546","website":"doc-demo.example.com","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/126.0 Safari/537.36","browser":"Chrome","os":"Linux","device":"Desktop","page":"/docs/getting-started","referrer":"https://www.google.com/","screenWidth":"1920","screenHeight":"1080","language":"zh-CN"}'
visit:200
落库结果(MongoDB visits 集合实测回显;注意官方脚本上报时 referrer 只保留域名部分):
{
"_id": ObjectId('6ae43d03e2dcaafdd48a6485'),
"project_id": ObjectId('6ae4267da0064c0b9a6c9546'),
"browser": "Chrome",
"os": "Linux",
"session": "676bde550d1b4aa71b51400ba82c95b1",
"flowHash": "efeb74ad83e1b42dd0ab77f67b1bb451",
"device": "desktop",
"website": "doc-demo.example.com",
"page": "/docs/getting-started",
"referrer": "www.google.com",
"created_at": ISODate('2026-10-30T06:45:23.529Z')
}
5.3 POST /keep_alive(在线心跳)
用于实时在线用户统计:心跳窗口 5 分钟,consumer 侧聚合出「实时在线」数。
$ curl -s -o /dev/null -w 'keep_alive:%{http_code}\n' -X POST http://localhost:8135/keep_alive \
-H 'Content-Type: application/json' \
-d '{"pid":"6ae4267da0064c0b9a6c9546","website":"doc-demo.example.com","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/126.0 Safari/537.36","instant":"true"}'
keep_alive:200
instant 字段同样以字符串传输(官方脚本传布尔值经 SDK 序列化,手工集成传 "true"/"false")。
5.4 兼容端点(v1,deprecated)
源码 producer/src/deprecated.ts 保留旧版路由,功能等价、字段形态偏旧(type: 0 为访问、其余为事件):
POST /v1/keep_alivePOST /v1/metrics/push
新集成一律使用 5.1–5.3 的现行端点。
5.5 错误码与静默丢弃行为(实测)
| 现象 | 实测回显 | 根因与处置 |
|---|---|---|
| 正常上报 | 200(空 body) | 入队成功,稍后落库 |
| 被 Shields 拦截(IP 在黑名单 / 开启 Bot 拦截且 UA 命中 600+ 模式 / 域名白名单不匹配) | 400(空 body) | producer 主动拒绝,不入队 |
| 请求体含数字类型值 | 500,body {"error":"Invalid argument type"} | Redis Stream 只收字符串,把 screenWidth:1920 改为 "1920" |
字段名错误(如 eventName 代替 name)或缺必填字段、pid 无效 | producer 仍 200,但 consumer 校验失败静默丢弃 | consumer 日志出现 events validation failed(缺 name)或 cast 失败;实测无效 pid 与缺 name 消息均未落库(visits/events 集合计数不变) |
采集端「宽松入队、消费端严格校验」是排查「上报 200 但看板无数据」的关键:先看 consumer 日志,再核对 Mongo 集合计数。
六、Dashboard 管理 API 详解
6.1 GET /api/project/list(项目列表)
$ curl -s -b cookies.txt http://localhost:8134/api/project/list
[{"_id":"6ae4267da0064c0b9a6c9546","owner":"6ae426011d60609133f012f1","name":"Doc Demo Site","created_at":"2026-10-30T05:09:17.270Z","__v":0}]
- 未携带有效会话:
401,响应{"error":true,"statusCode":401,"message":"Unauthorized"}; - 返回数组按创建时间排列,无分页参数(自托管项目量小,全量返回)。
6.2 GET /api/project/stats(流量趋势)
$ curl -s -b cookies.txt 'http://localhost:8134/api/project/stats?pid=6ae4267da0064c0b9a6c9546'
{"chart":{"labels":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,1]}}
- 查询参数:
pid(项目 ID); - 固定返回最近 24 小时按小时切片的访问计数(
labels为时间刻度、data为计数,实测上报的 4 次 visit + 1 次 keep_alive 触发的访问计入末位); pid非本人项目时返回空(服务端按owner过滤)。
6.3 GET /api/project/live_users(实时在线)
$ curl -s -b cookies.txt -H 'x-pid: 6ae4267da0064c0b9a6c9546' \
'http://localhost:8134/api/project/live_users?pid=6ae4267da0064c0b9a6c9546'
1
- 同时需要两处传 pid:查询串
?pid=与请求头x-pid(缺头实测报400,messagex-pid is required); - 返回数字:最近 5 分钟内有心跳/访问的去重会话数(实测上报后立即查询返回
1)。
6.4 其他管理端点
/api 前缀下另有 domains(域名白名单)、shields(防护配置)、timeline(明细)、snapshot、members(成员)、raw(导出)等路由组(源码 dashboard/server/api/ 目录)。自托管实践中以看板 UI 操作为主,本文覆盖的登录/项目/统计/实时四组为集成常用最小集。
七、分页/过滤/排序通用约定
- 管理 API 无统一分页参数:
/api/project/list全量返回;stats固定 24 小时窗口;明细数据在看板内通过timeline路由组按pid+ 时间范围查询; - 过滤维度(浏览器/OS/国家/页面等)在看板端聚合完成,管理 API 层不暴露;
- 大批量数据获取建议直接读 MongoDB(只读账号):核心集合
visits/events/sessions/aggregations,按project_id+created_at索引查询(索引定义见源码 schema)。
八、常见问题
一、上报一直 200 但看板没数据
按序排查:① STREAM_NAME 两侧一致性;② consumer 是否存活(Start reading loop);③ consumer 日志有无 events validation failed(字段名/类型错误,见 5.5);④ Mongo 集合计数比对。配置核对方法见 《Litlyx v0.0.19 配置参数详解》。
二、cURL 模拟上报返回 500 Invalid argument type
请求体有数字/布尔类型值。Redis Stream 只接受字符串,所有值一律加引号(实测案例见部署篇常见问题五)。
三、采集端点没有认证,安全吗
设计如此:公开端点 + 无 Cookie 方案(否则无法免同意横幅)。防滥用依赖 Shields(IP 黑名单、Bot 拦截、域名白名单,看板内配置)。暴露公网时建议反代限流,并仅放行 /event、/visit、/keep_alive 路径。
四、实时在线数一直是 0
live_users 只统计最近 5 分钟有 visit 或 keep_alive 的会话;确认上报侧 UA 未命中 Bot 拦截、且查询时带了 x-pid 请求头。
五、管理 API 返回 401
会话 Cookie 缺失或失效(7 天过期 / NUXT_SESSION_PASSWORD 被更换)。重新登录获取即可,登录方式见第四章。
九、参考链接
- 官方 README 采集 API 示例(cURL 直报):https://github.com/litlyx/litlyx
- 官方文档站 SDK 文档:https://docs.litlyx.com
- 采集端点源码:https://github.com/litlyx/litlyx(`producer/src/index.ts`、`producer/src/deprecated.ts`)
- 部署与环境准备:本专栏 《Litlyx Docker Compose 部署指南》
- 产品认知与版本背景:本专栏 《Litlyx 介绍与选型指南》
- 同类平台 API 参照:《Swetrix API 使用详解》