🤖 给 Agent(和写 curl 的人)

本页是 Lighthouse Server 的完整接口说明。机器想直接读?用 /llms.txt(纯文本)或 /api/manifest(JSON)。 需要完整 schema 用 /openapi.json 或 Swagger UI。

鉴权

写操作需要 Bearer Token;读操作(列表、下载)免鉴权。

Authorization: Bearer <API_TOKEN>

⚠️ 别把两件事搞混:这里的 Bearer token 是认证凭据; /api/files/{file_id} 里的 file_id 是文件的资源 ID, 两者毫无关系。file_id 旧名叫 token,该别名已移除—— 还在读响应里 token 字段的客户端请改用 file_id。 已发出的下载链接不受影响(URL 里只有 id,没有字段名)。

服务端环境变量 API_TOKEN 即 token 值。需要鉴权的接口: POST /api/files/upload、DELETE /api/files/{file_id}、 POST /api/tweets、POST /api/tweets/batch、POST /api/download。

文件仓库

上传任意文件 → 拿到一条免鉴权、可分享的下载链接;列表返回每个文件的上传时间。

上传

curl -X POST $BASE/api/files/upload \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@./report.pdf" \
  -F "description=Q3 report"

返回 201:{ file_id, filename, size, content_type, uploaded_at, description, public, download_url }

想让大家都能下载(例如 APK)?上传时加 -F "public=true"。 公开文件会出现在 /files 页面的「公开文件」区,并可免 Token 调用 GET /api/public/files 与 GET /api/public/files/{file_id}/{filename}。

列出(带时间)

curl "$BASE/api/files?page=1&page_size=50&order=recent&q=report"

order:recent(默认,最新在前)| oldest | name | largest。 q 匹配文件名与备注。返回 { total, page, page_size, items: [FileMeta] }。

下载 / 预览 / 删除

curl -OJ $BASE/api/files/{file_id}/{filename}
curl "$BASE/api/files/{file_id}/{filename}?inline=1"   # 图片/视频浏览器内预览
curl -X DELETE $BASE/api/files/{file_id} -H "Authorization: Bearer $TOKEN"

推文归档

两条路:贴 URL 交给 gallery-dl 抓;或直接提交 JSON(批量导入最快,无需下载器)。

直接导入(推荐给 Agent)

curl -X POST $BASE/api/tweets \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "tweet_id": "1234567890",
    "author_name": "Jane Doe",
    "author_handle": "janedoe",
    "content": "hello world",
    "date": "2026-09-06T12:00:00Z",
    "source_url": "https://x.com/janedoe/status/1234567890",
    "media_urls": [], "media_types": [],
    "stats": {"likes": 42, "retweets": 7}
  }'

# 批量:1–500 条,部分失败不会中断整批
curl -X POST $BASE/api/tweets/batch \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"tweets": [{ "tweet_id": "1", "author_name": "A", "author_handle": "a" }]}'

tweet_id 即主键,重复提交会覆盖(幂等)。必填:tweet_id、author_name、author_handle。

浏览

curl "$BASE/api/tweets?page=1&page_size=20&q=python&author=janedoe&order=score"
curl $BASE/api/tweets/authors        # 作者 + 推文数 + 最近归档时间
curl $BASE/api/tweets/{tweet_id}       # 单条,media_urls 每次重新签发
curl -X POST $BASE/api/tweets/{tweet_id}/vote -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"delta": 1}'
curl -X POST $BASE/api/tweets/{tweet_id}/comments -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"content": "nice"}'
curl $BASE/api/tweets/{tweet_id}/comments  # 按分数降序

默认 order=score:按净票数降序,同分按时间倒序;order=timeline 为纯时间倒序。投票与留言为单用户模式,无需账号。

故事 / 个人笔记

卡片流 /stories:只写正文,无需标题;按最后编辑时间倒序,可筛选标签、搜索、编辑与删除。

curl "$BASE/api/stories?page=1&page_size=20&tag=日记"
curl -X POST $BASE/api/stories -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"content": "去了海边", "tags": "日记, 旅行、随想; #读书"}'
curl -X PUT $BASE/api/stories/{story_id} -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"content": "改过的正文", "tags": ["日记"]}'
curl -X DELETE $BASE/api/stories/{story_id} -H "Authorization: Bearer $TOKEN"

标签可用中英文逗号、顿号、分号、空格(含「逗号+空格」)分隔;tags 也可直接传字符串,服务端会拆分并去掉 # 前缀与重复项。列表额外返回 tags[{name,count}] 标签云。

按 URL 抓取(gallery-dl)

异步任务:提交后轮询 job,直到 done 或 failed。

curl -X POST $BASE/api/download \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"url": "https://x.com/janedoe/status/1234567890"}'
# → 202 { job_id, status: "pending" }

curl $BASE/api/jobs/{job_id}
# pending → downloading → uploading → done | failed(失败时带 error 字段)

优先用 gallery-dl(需服务端配置 TWITTER_AUTH_TOKEN + TWITTER_CT0);若 gallery-dl 缺失或失败,自动回退到公开的 FxTwitter / VxTwitter 接口(无需 cookie,可取公开帖子)。

错误处理

错误响应统一为 {"detail": "给人看的", "code": "给程序看的"}。请按 code 分支,把 detail 展示给人。

codeHTTP含义 / 怎么修
unauthorized401缺 Bearer Token 或 token 错误 —— 检查请求头与服务端 API_TOKEN
invalid_order422/api/files 的 order 只能是 recent / oldest / name / largest
file_not_found404token 不存在,或文件名不匹配 —— 先 GET /api/files/{file_id} 取准确文件名
invalid_token404token 格式非法(长度/字符不对),多半是拼错了
upload_too_large413超过服务端 MAX_UPLOAD_SIZE_MB(默认 2048,即 2GB)
write_failed500服务端写盘失败(磁盘满 / 权限)—— 重试或联系运维
delete_failed500服务端删除失败
storage_error502推文存储后端(local / COS)不可用
internal_error500其它 —— 把响应体里的 request_id 给运维查日志

两个例外

每个响应都带 X-Request-ID 头;5xx 响应体里重复一次 request_id,便于凭它查服务端日志。

约定

时间格式
UTC ISO-8601,例如 2026-09-06T12:34:56.789012+00:00
分页
page 从 1 开始;响应含 total / page / page_size / items
媒体 URL
可能是相对路径(如 /storage/media/…),需拼上服务器地址
错误
非 2xx 返回 { "detail": "…" }
CORS
全部放开(Access-Control-Allow-Origin: *)
健康检查
GET /health → { status, queue_size, storage_backend }

数据字段

对象字段
FileMeta token, filename, size, content_type, uploaded_at, description, download_url
TweetMeta tweet_id, author_name, author_handle, author_avatar, content, date, media_urls, media_types, stats{likes,retweets,replies,bookmarks,views}, status, source_url, archived_at, score, comment_count
AuthorInfo handle, name, avatar, tweet_count, latest_date
JobStatus job_id, url, status, created_at, tweet_id, error