http api

面板能做的一切,都能在终端里做

一把账号密钥。列出你的网站、往上面部署、重命名、读取表单收到的内容、删除它们 —— 都走朴素的 HTTP,从脚本、CI 任务或智能体发起。

快速上手

三条命令

在面板里创建一把密钥,确认它能用,然后把一个文件夹发到线上。每次调用都把密钥放进 Authorization 请求头。

确认密钥可用
curl -H "Authorization: Bearer hvs_…" https://harvis.dev/api/v1
看看账号里有什么
curl -H "Authorization: Bearer hvs_…" https://harvis.dev/api/v1/sites
发布一个文件夹
curl -X POST https://harvis.dev/api/v1/sites \
  -H "Authorization: Bearer hvs_…" \
  -F "files=@index.html" -F "paths=index.html"
一份契约

网页应用和 API 不会各走各的

每项能力只在一个文件里声明一次,网页应用和这个 API 都由它构建。openapi.json 从那份声明生成,两者不一致时构建会失败。所以这不是描述产品的文档 —— 它就是产品本身的构成。

  • 每项能力只有一个实现,网页应用和你的脚本调用的是同一个。
  • openapi.json 由生成得来,从不手写,并在 /openapi.json 提供。
  • 只要路由、契约和文档不再一致,构建就会失败。
部署

有密钥,网站立刻就属于你

不带账号部署依然可用,而且会一直可用 —— 你会拿到一个私有的认领链接,稍后打开。若在同一次调用里带上密钥,就没有什么需要认领:从第一个字节起,网站就在你的账号里,而且永不过期。

zip -r site.zip . && curl -X POST https://harvis.dev/api/upload \
  -H "Authorization: Bearer hvs_…" \
  -H "Content-Type: application/zip" --data-binary @site.zip
端点

全部接口

完整的请求与响应结构都在 OpenAPI 文档里。

方法路径作用
GET/api/v1Check that a credential works.
GET/api/v1/keysThe account's API keys. Revoked keys are not listed.
POST/api/v1/keysCreate an API key.
DELETE/api/v1/keys/{keyId}Revoke an API key. Anything using it stops working immediately.
GET/api/v1/meThe account a credential belongs to.
GET/api/v1/sitesList the account's sites, newest first.
POST/api/v1/sitesCreate a site from a folder of files.
DELETE/api/v1/sites/{id}Delete a site, its files and its form submissions.
GET/api/v1/sites/{id}One site.
PATCH/api/v1/sites/{id}Rename a site, change its web address, or both.
POST/api/v1/sites/{id}/deployReplace every file of a site with the uploaded set.
POST/api/v1/sites/{id}/deploy-tokenIssue a new deploy token for a site. The old one stops working immediately.
POST/api/v1/sites/{id}/deploy/zipReplace every file of a site from a zip archive sent as the raw request body.
GET/api/v1/sites/{id}/filesEvery file a site is serving.
POST/api/v1/sites/{id}/filesAdd or overwrite individual files, leaving the rest of the site alone.
DELETE/api/v1/sites/{id}/submissionsDelete every submission for a site, or every one of a single form.
GET/api/v1/sites/{id}/submissionsOne page of a site's form submissions, newest first.
DELETE/api/v1/sites/{id}/submissions/{submissionId}Delete one submission.
GET/api/v1/sites/{id}/submissions/{submissionId}One submission.
GET/api/v1/sites/{id}/submissions/csvExport a site's form submissions as CSV.
POST/api/v1/sites/{id}/submissions/readMark every unread submission as read.
GET/api/v1/sites/{id}/submissions/summaryHow many submissions a site holds, how many are unread, and which forms exist.
POST/api/v1/sites/importCreate a site by downloading a single page from a known artifact URL.
错误

每个失败都是同一种形状

按 code 分支,永远不要按 message。code 是稳定的;那段文字是给读日志的人看的。

{
  "error": {
    "code": "subdomainTaken",
    "message": "That address is already taken. Try another."
  }
}