Plausible API 使用详解

逐条 curl 实测 Plausible CE v3.2.1 三组 API:Stats API v1(realtime/aggregate/timeseries/breakdown 的 date_range/metrics/filters 组合与 7 类错误分支)、Query API v2(dimensions+filter_tree+schema)、Events API 采集上报(pageview/自定义事件 props 与 6 类边界分支),全部响应 JSON 实测照抄。

PlausiblePlausible2026/10/18

Plausible API 使用详解

‍‍​​‌​> 目标:面向开发者讲清 Plausible 的三组 API——Stats API(v1,GET 查询)、Query API(v2,POST 查询)、Events API(采集上报)——并用逐条 curl 实测覆盖参数组合与错误分支。本文全部请求与响应 JSON 均在实测环境(Plausible CE v3.2.1)执行并照抄;部署与环境准备见《Plausible Docker Compose 部署指南》,参数调优见《Plausible 配置参数详解》。

一、环境信息

项目值
操作系统Ubuntu 22.04.4 LTS
组件版本Plausible CE v3.2.1
服务地址http://192.168.146.128:13910(下文示例统一用 http://127.0.0.1:13910)
演示站点mysite.dev(已通过《Plausible Docker Compose 部署指南》4.7 节埋点实测积累数据)
测试账号admin@example.com(API Key:qzuo-demo-key-2026,实测创建)
实测日期2026-10-18
事件数据事件库 events_v2 实测累计 5 条事件(4 条 pageview + 1 条自定义事件 signup)

二、API 概览与认证

API方法与路径用途认证
Stats API(v1)GET /api/v1/stats/*实时/聚合/时序/分组查询Authorization: Bearer <key>
Query API(v2)POST /api/v2/query复杂查询(多维度/过滤树/分页)同上
Events APIPOST /api/event埋点上报(页面浏览/自定义事件)无需认证(等同浏览器脚本)
Sites APIPOST /api/v1/sites/*站点与目标管理同 Stats API(本文不展开)

API Key 创建:

  • UI 路径(官方文档口径):登录 → 右上角账号名 → Settings → API Keys → New API Key(Key 只显示一次);
  • 本文为可复现实测,通过应用内置 CLI 创建(在应用服务内执行,等价于 UI 操作):
/app/bin/plausible rpc \
  'user = Plausible.Repo.get!(Plausible.Auth.User, 1); {:ok, team} = Plausible.Teams.get_or_create(user); res = Plausible.Auth.create_stats_api_key(user, team, "docs-demo", "qzuo-demo-key-2026"); IO.inspect(res, label: "APIKEY")'

实测回显(节选):

{:ok,
 %Plausible.Auth.ApiKey{
   ...
   user_id: 1,
   name: "docs-demo",
   key: "qzuo-demo-key-2026",
   inserted_at: ~N[2026-10-17 22:58:44],
   updated_at: ~N[2026-10-17 22:58:44]
 }}

📌 Key 按**团队(Team)**隔离:只能查询创建时所属团队的站点(官方文档明示)。限流:官方文档注明默认 600 请求/小时(2026-10-18 抓取 https://plausible.io/docs/stats-api )。

三、快速开始

# 1. 配置认证头(示例值,请替换为你的 Key)
K='Authorization: Bearer qzuo-demo-key-2026'

# 2. 查一次聚合
curl -s -H "$K" \
  'http://127.0.0.1:13910/api/v1/stats/aggregate?site_id=mysite.dev&period=day&metrics=visitors,pageviews'

# 3. 上报一条页面浏览
curl -s -X POST http://127.0.0.1:13910/api/event \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) Chrome/126 Safari/537.36' \
  -d '{"name":"pageview","domain":"mysite.dev","url":"http://mysite.dev/"}'
# 响应:ok(HTTP 202),约 5 秒后落库可查

四、Stats API 详解(/api/v1/stats)

4.1 realtime visitors(实时访客)

请求:

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/realtime/visitors?site_id=mysite.dev'

实测序列(响应为纯文本数字,非 JSON):

时点实测返回说明
发送 1 条 pageview 后立即查询0事件还在内存缓冲(默认 5 秒刷盘)
补发 1 条并等待约 30 秒2近 5 分钟窗口内 2 名访客
完整 down → up 循环 + 1 条新 pageview 后1历史会话已滑出 5 分钟窗口

参数:仅 site_id(站点域名)。

4.2 aggregate(聚合指标)

① 常用指标组合(period=day):

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/aggregate?site_id=mysite.dev&period=day&metrics=visitors,pageviews,bounce_rate,visit_duration,views_per_visit,visits'

实测响应(当天累计 4 次访问):

{
    "results": {
        "pageviews": {
            "value": 4
        },
        "visit_duration": {
            "value": 117
        },
        "visitors": {
            "value": 4
        },
        "visits": {
            "value": 4
        },
        "bounce_rate": {
            "value": 50
        },
        "views_per_visit": {
            "value": 1.0
        }
    }
}

② 自定义日期范围(period=custom):

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/aggregate?site_id=mysite.dev&period=custom&date=2026-10-17,2026-10-18&metrics=visitors,pageviews'

实测响应:

{"results":{"pageviews":{"value":4},"visitors":{"value":4}}}

③ 带过滤条件(filters):只看 /pricing 页:

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/aggregate?site_id=mysite.dev&period=custom&date=2026-10-17,2026-10-18&metrics=visitors,pageviews&filters=event:page==/pricing'

实测响应:

{"results":{"pageviews":{"value":2},"visitors":{"value":2}}}

参数小结:

参数取值(实测验证)说明
site_id站点域名,如 mysite.dev必填
periodday / 7d / 30d / custom 等自定义需配合 date
dateYYYY-MM-DD 或 起,止(逗号分隔)custom 时用;实测 2026-10-17,2026-10-18 有效
metrics逗号分隔,实测有效:visitors、pageviews、bounce_rate、visit_duration、views_per_visit、visits、events_per_session、time_on_page无效指标返回 400(见 4.5)
filters维度==值,如 event:page==/pricing过滤维度详见 4.4

4.3 timeseries(时序数据)

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/timeseries?site_id=mysite.dev&period=custom&date=2026-10-17,2026-10-18&metrics=visitors,pageviews&interval=date'

实测响应(事件集中在 10-17,10-18 为 0):

{
    "results": [
        {
            "date": "2026-10-17",
            "pageviews": 4,
            "visitors": 4
        },
        {
            "date": "2026-10-18",
            "pageviews": 0,
            "visitors": 0
        }
    ]
}

参数:在 aggregate 基础上增加 interval(date/hour/month,实测 date 按天聚合)。

4.4 breakdown(维度分组)

① 按页面分组:

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/breakdown?site_id=mysite.dev&property=event:page&period=custom&date=2026-10-17,2026-10-18&metrics=visitors,pageviews,bounce_rate,time_on_page'

实测响应:

{
    "results": [
        {
            "page": "/pricing",
            "pageviews": 2,
            "visitors": 2,
            "time_on_page": null,
            "bounce_rate": 100
        },
        {
            "page": "/",
            "pageviews": 1,
            "visitors": 1,
            "time_on_page": null,
            "bounce_rate": 0
        },
        {
            "page": "/blog/hello-world",
            "pageviews": 1,
            "visitors": 1,
            "time_on_page": null,
            "bounce_rate": 100
        },
        {
            "page": "/register",
            "pageviews": 0,
            "visitors": 1,
            "time_on_page": null,
            "bounce_rate": 0
        }
    ]
}

⚠️ 实测发现:time_on_page 在 breakdown 中返回 null(该指标在分组场景无数据),但 aggregate 中可正常返回数值——分组查询建议改用 visit_duration。

② 按来源分组:

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/breakdown?site_id=mysite.dev&property=visit:source&period=custom&date=2026-10-17,2026-10-18&metrics=visitors'

实测响应:

{"results":[{"source":"Direct / None","visitors":4}]}

③ 按浏览器分组:

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/breakdown?site_id=mysite.dev&property=visit:browser&period=custom&date=2026-10-17,2026-10-18&metrics=visitors'

实测响应:

{"results":[{"browser":"Chrome","visitors":3},{"browser":"Safari","visitors":1}]}

④ 分组 + 过滤组合:各浏览器在 /pricing 页的访客:

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' \
  'http://127.0.0.1:13910/api/v1/stats/breakdown?site_id=mysite.dev&property=visit:browser&period=custom&date=2026-10-17,2026-10-18&metrics=visitors&filters=event:page==/pricing'

实测响应:

{"results":[{"browser":"Chrome","visitors":2}]}

常用维度前缀(实测验证 event:page、visit:source、visit:browser):event:* 为事件属性(如 event:page、event:url、自定义 event:props:xxx);visit:* 为会话属性(如 visit:source、visit:browser、visit:os、visit:device、visit:country、visit:entry_page、visit:exit_page)。

4.5 错误分支实测

场景请求实测响应
无认证curl -s '.../aggregate?site_id=mysite.dev&period=30d&metrics=visitors'{"error":"missing or invalid API key"}
错误 Key-H 'Authorization: Bearer wrong-key'{"error":"invalid api key"}
未知站点site_id=noexist.dev{"error":"could not find site with domain \"noexist.dev\""}
未知指标metrics=foo{"error":"Invalid metrics"}
缺 site_id.../aggregate?period=day&metrics=visitors{"error":"site_id is required"}
非法 filterfilters=page==/x{"error":"invalid filter: page==/x"}
指标不适用metrics=visitors,time_on_page(day 聚合)正常返回,time_on_page 值为 null(分组/特定窗口才有值)

五、Query API(v2,POST /api/v2/query)

v2 是官方当前主推的查询接口:单端点、JSON 请求体,支持维度、过滤树与分页;模式由 /api/docs/query/schema.json 公开(实测可获取)。

5.1 基本聚合

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' -H 'Content-Type: application/json' \
  -X POST http://127.0.0.1:13910/api/v2/query \
  -d '{"site_id":"mysite.dev","metrics":["visitors","pageviews","bounce_rate"],"date_range":["2026-10-17","2026-10-18"]}'

实测响应:

{
    "results": [
        {
            "metrics": [
                4,
                4,
                50
            ],
            "dimensions": []
        }
    ],
    "meta": {},
    "query": {
        "site_id": "mysite.dev",
        "metrics": [
            "visitors",
            "pageviews",
            "bounce_rate"
        ],
        "date_range": [
            "2026-10-17T00:00:00Z",
            "2026-10-18T23:59:59Z"
        ],
        "filters": [],
        "dimensions": [],
        "order_by": [
            [
                "visitors",
                "desc"
            ]
        ],
        "include": {},
        "pagination": {
            "offset": 0,
            "limit": 10000
        }
    }
}

📌 响应的 query 字段回显了服务端解析结果(date_range 被规范化为 UTC 起止时刻,默认排序 visitors desc,分页默认 limit: 10000)。

5.2 维度 + 过滤

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' -H 'Content-Type: application/json' \
  -X POST http://127.0.0.1:13910/api/v2/query \
  -d '{"site_id":"mysite.dev","metrics":["visitors","pageviews"],"date_range":["2026-10-17","2026-10-18"],"filters":[["is","event:page",["/pricing"]]],"dimensions":["event:page"]}'

实测响应(metrics 与 dimensions 数组按位对应):

{
    "results": [
        {
            "metrics": [
                2,
                2
            ],
            "dimensions": [
                "/pricing"
            ]
        }
    ],
    "meta": {},
    "query": {
        "site_id": "mysite.dev",
        "metrics": [
            "visitors",
            "pageviews"
        ],
        "date_range": [
            "2026-10-17T00:00:00Z",
            "2026-10-18T23:59:59Z"
        ],
        "filters": [
            [
                "is",
                "event:page",
                [
                    "/pricing"
                ]
            ]
        ],
        "dimensions": [
            "event:page"
        ],
        "order_by": [
            [
                "visitors",
                "desc"
            ]
        ],
        "include": {},
        "pagination": {
            "offset": 0,
            "limit": 10000
        }
    }
}

5.3 请求体 Schema(实测自 schema.json)

curl -s http://127.0.0.1:13910/api/docs/query/schema.json | python3 -m json.tool

实测关键定义(照抄):

  • 必填字段:site_id、metrics、date_range;
  • date_range:两个 ISO8601 日期的数组({"minItems": 2, "maxItems": 2, "items": {"format": "date", "type": "string"}}),示例 ["2024-09-01", "2024-09-30"];
  • filter_tree:filter_entry / filter_and_or / filter_not / filter_has_done 的 oneOf 组合,支持 is/contains/matches(正则)/wildcard 等操作;
  • dimensions:simple_filter_dimensions / custom_property_filter_dimensions / goal_dimension / time_dimensions 之一。

校验错误实测(非法 date_range):

curl -s -H 'Authorization: Bearer qzuo-demo-key-2026' -H 'Content-Type: application/json' \
  -X POST http://127.0.0.1:13910/api/v2/query \
  -d '{"site_id":"mysite.dev","metrics":["visitors","pageviews"],"date_range":"bad"}'

实测响应:

{"error":"#/date_range: Invalid date range \"bad\""}

六、Events API(POST /api/event)

采集上报接口,无需认证(与浏览器埋点脚本同源),仅接受 POST。

6.1 页面浏览

curl -s -w '\nHTTP %{http_code}\n' -X POST http://127.0.0.1:13910/api/event \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' \
  -d '{"name":"pageview","domain":"mysite.dev","url":"http://mysite.dev/"}'

实测响应:

ok
HTTP 202

字段说明:name(事件名,页面浏览固定 pageview)、domain(站点域名)、url(完整页面地址,用于解析路径/来源);UA 决定浏览器/操作系统/设备维度,缺 UA 会影响这些维度取值。

6.2 自定义事件与属性(props)

curl -s -w ' [HTTP %{http_code}]\n' -X POST http://127.0.0.1:13910/api/event \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' \
  -d '{"name":"signup","domain":"mysite.dev","url":"http://mysite.dev/register","props":{"plan":"pro","amount":99}}'

实测响应:

ok [HTTP 202]

事件落库验证(事件库 clickhouse-client 直查实测):

SELECT name, count() AS c FROM plausible_events_db.events_v2 GROUP BY name ORDER BY c DESC;
pageview	4
signup	1

📌 自定义事件要在仪表盘显示为转化目标,需在站点设置中添加同名 Goal(本文实测仅验证上报与落库)。

6.3 错误与边界分支实测

场景请求体/方式实测响应
缺 url{"name":"pageview","domain":"mysite.dev"}{"errors":{"url":["is required"]}} 400
空 body{}{"errors":{"domain":["can't be blank"],"url":["is required"],"event_name":["can't be blank"]}} 400
缺 domain(有 url){"name":"pageview","url":"http://x.dev/"}ok 202(宽松接受,但事件无法归属站点,勿依赖)
未知站点{"name":"pageview","domain":"no-such.dev","url":"http://no-such.dev/"}ok 202(也返回 202,事件实际未入库——防探测设计,见下)
GET 请求GET /api/event404 HTML 错误页(<h1>404</h1>)
非 JSON Content-Type-H 'Content-Type: text/plain' + 合法 JSONok 202(服务端宽松解析,规范仍要求 application/json)

💡 关键发现:对未知站点上报也返回 202 ok(响应内容与成功一致,事件不会入库)。因此不能用 Events API 的响应判断站点是否存在;上报成功与否的可靠验证方式是查事件库或稍后查 Stats API。

时效注意:事件先入内存缓冲,默认每 5 秒(CLICKHOUSE_FLUSH_INTERVAL_MS=5000)批量刷入事件库(实测见《Plausible 配置参数详解》5.3),发送后立即查询可能看不到。

七、错误处理与限流

  • 认证错误统一返回 {"error": "..."}(HTTP 401/403),文案见 4.5;
  • 参数校验错误:v1 返回 400 + error 文案;v2 返回 400 + JSON Schema 路径(如 #/date_range: ...);Events API 返回 400 + errors 字段级错误;
  • 限流:官方文档注明默认 600 请求/小时,超限返回 429(本文未触发实测该阈值);
  • 调试建议:先打 /api/health 确认服务正常,再打 /api/v1/stats/aggregate?period=day&metrics=visitors 最小化验证认证与站点归属,最后逐步加参数。

八、常见问题(FAQ)

Q1:realtime visitors 返回的是数字不是 JSON?

是。该端点返回纯文本整数(实测 2),脚本解析时注意别按 JSON 处理。

Q2:发完事件马上查不到数据?

5 秒缓冲 + 查询缓存所致(实测发送后立即查 0,约 30 秒内出现)。相关参数见《Plausible 配置参数详解》5.3。

Q3:breakdown 里 time_on_page 是 null?

该指标在分组场景无数据(实测返回 null),分组统计改用 visit_duration。

Q4:自定义事件上报 202 了,仪表盘为什么没有转化数据?

202 只代表事件被接受且入库;要在仪表盘展示为转化,还需在站点设置里添加同名目标(Goal)。实测确认事件已落库(6.2)。

Q5:Events API 能否用来探测站点是否存在?

不能。未知站点同样返回 202(实测 6.3),需用 Stats API 或界面确认。

Q6:v1 与 v2 该用哪个?

新集成建议 v2(单端点、过滤树、分页、schema 自描述);v1 适合简单 GET 集成与脚本调试。两者指标名一致。

九、参考链接