REST API 参考

用于在 GET /api/v1/... 查询已存储 Nostr 事件的只读 HTTP API — 端点、参数、分页、可见性规则和错误。

基础 URL

API 在 /api/v1 下提供,与 WebSocket 中继同一端口:

text
http://<host>:<port>/api/v1/{identifier}
http://<host>:<port>/api/v1/{identifier}/{kind}

主机路由(server.api_host)

配置 server.api_host(例如 api.example.com)后,API 和中继 按 Host 头拆分:api.example.com 获得 /api/v1、 /health 和 /metrics;任何其他主机获得 WebSocket 中继和 NIP-11。 没有 api_host 时,API 在每个主机上提供。只支持 GET — 到 /api/v1 的 WebSocket 升级请求会以 403 拒绝。

端点

基于标识符的路径

路径返回
GET /api/v1/<npub1...>最新的 kind-0 个人资料事件
GET /api/v1/<note1> / <nevent1>具有此 id 的单个事件
GET /api/v1/<naddr1>该地址的事件(kind + 作者 + d 标签)
GET /api/v1/<npub1...>/<kind>按公钥、按类型过滤的事件(接受 npub1... 或 nprofile1...;否则 400)

作者标识符在每个端点上接受 npub1...、nprofile1... 或 64 位十六进制公钥 (不区分大小写)。

查询和聚合端点

  • GET /api/v1/query — 不带标识符的通用过滤器查询。
  • GET /api/v1/count — 相同过滤器参数的总计数(NIP-45 语义)。
  • GET /api/v1/<npub1...>/kinds — 作者按类型的事件计数,最常用的 在前。
  • GET /api/v1/<npub1...>/<kind>/daily — 某个月的按日计数; month 必须为 1-12,每天都以零填充报告到最后一天(每个条目和 总计都带 approximate 标志)。
  • GET /api/v1/ids/<hex> — 按其 64 位十六进制 id 获取单个事件(拒绝前缀)。
  • GET /api/v1/<npub1...>/stats — 作者摘要(总计、首次/最后活动、类型 细分);没有可见事件时 first_seen/last_seen/月份为 null。
  • GET /api/v1/<npub1...>/<kind>/hourly — 某一天的按小时计数;全部 24 小时都报告,零填充(与 daily 相同的 approximate 标志)。
  • GET /api/v1/ids/<hex>/related — 引用该事件的回复(#e)和引用(#q); 路径 id 在匹配前会转换为小写,e 查询参数会 OR 到 #e 一侧。
  • GET /api/v1/<npub1...>/follows — 作者最新的 kind-3 关注列表。
  • GET /api/v1/relay/kinds — 中继上最常见的类型(有界、可见性过滤的样本;approximate 和 filtered 标志)。
  • GET /api/v1/relay/top-authors — 中继上最活跃的作者(有界、 可见性过滤的样本;approximate 和 filtered 标志)。
  • GET /api/v1/<npub1...>/relays — 作者最新的 NIP-65 中继列表 (kind 10002)。
  • GET /api/v1/<npub1...>/<kind>/monthly — 按月计数,在 since/until 范围内零填充(默认:整个期间;上限 120 个月)。

查询参数

参数说明
limit最大结果数(默认 100,受 max_api_limit 限制)
offset跳过的可见结果数(分页)
since只包含 created_at >= since 的事件
until只包含 created_at <= until 的事件
sortasc/ascending 表示最旧在前;默认最新在前
searchNIP-50 全文搜索(全词匹配)
e / p / t / d按 #e / #p / #t / #d 标签过滤
no_p / no_e / no_t / no_d排除携带该标签的事件 — 在分页前应用,因此被排除的事件永远不会 占用 limit 槽位或 offset 步数

响应格式

成功的响应返回 200 OK 和以下 JSON 正文:

json
{
  "events": [
    {
      "id": "32 字节十六进制事件 id",
      "pubkey": "32 字节十六进制公钥",
      "created_at": 1700000000,
      "kind": 1,
      "tags": [["t", "example"]],
      "content": "hello",
      "sig": "64 字节十六进制签名"
    }
  ],
  "count": 1,
  "more": false
}
字段说明
events本页的事件(默认最新在前)
count本页的事件数
more存在更多页时为 true(用 offset 获取它们)

分页

分页通过 offset 和 more 标志完成,在 可见序列上计算 — 隐藏事件永远不会跳过或重复一页:

sh
curl "http://127.0.0.1:8080/api/v1/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkws3w8ktc/1?limit=50&offset=0"     # 第 1 页
curl "http://127.0.0.1:8080/api/v1/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkws3w8ktc/1?limit=50&offset=50"    # 第 2 页(当 more 为 true 时)
端点怪癖
单例端点(个人资料、/ids/{hex}、关注、中继列表)仍接受 offset — ?offset=1 会跳过唯一的事件并返回 []。 authors/kinds 查询参数只过滤通用的 /query 端点:在 kind 端点上它们被静默忽略(两者都已预填),而在 id 端点上它们被 AND 组合。stats 的类型细分按类型排序,不同于 /kinds(按计数优先)。

可见性规则

API 未认证,因此它会保留与匿名 WebSocket 连接相同的事件:

  • NIP-70 受保护事件(携带 - 标签)
  • NIP-59 礼物包装(kind 1059)
  • NIP-29 私密/隐藏群组内容(仅成员可见)

错误与状态码

代码含义
200成功
400无效的标识符或查询参数
403对 /api/v1 的 WebSocket 升级尝试
404未知路径,或 API 的 Host 错误(配置了 api_host)
503达到 API 并发限制 — 请稍后重试

示例

获取用户的笔记(最新在前):

sh
curl "http://127.0.0.1:8080/api/v1/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkws3w8ktc/1"

分页和排序:

sh
curl "http://127.0.0.1:8080/api/v1/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkws3w8ktc/1?limit=10&offset=10&sort=asc"

按 id 获取单个事件(note1... 或 nevent1... 都可用):

sh
curl "http://127.0.0.1:8080/api/v1/note1..."
curl "http://127.0.0.1:8080/api/v1/nevent1..."

获取可寻址事件(naddr1...):

sh
curl "http://127.0.0.1:8080/api/v1/naddr1..."

搜索:

sh
curl "http://127.0.0.1:8080/api/v1/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkws3w8ktc/1?search=rust"

标签过滤:

sh
curl "http://127.0.0.1:8080/api/v1/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkws3w8ktc/7?e=<event-id>&limit=100"