API 与 AI 代理访问
SimplyQuote 提供 REST API,让您的 AI 代理、脚本和集成能够代表您处理报价单和发票。访问通过可撤销、带范围限制的个人访问令牌进行控制。
1. 启用 API 访问
- 打开设置页面并登录
- 滚动到「API 与 AI 代理访问」部分。
- 为令牌命名,选择范围,然后点击「创建令牌」。
- 立即复制令牌——出于安全考虑,它只显示一次。
2. 发起请求
在 Authorization 头中以 Bearer 令牌的形式发送令牌:
curl https://simplyquote.net/api/v1/quotes \ -H "Authorization: Bearer sq_your_token_here"
3. 创建和更新文档
创建和更新报价单与发票使用同一个令牌并需要写范围。总额始终由服务器根据您提交的条目计算:
curl -X POST https://simplyquote.net/api/v1/quotes \
-H "Authorization: Bearer sq_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Acme Ltd",
"client_email": "billing@acme.example",
"items": [
{ "description": "Consulting", "quantity": 4, "unit_price": 120 },
{ "description": "Hosting (1 month)", "quantity": 1, "unit_price": 30 }
],
"currency": "USD",
"tax_rate": 10,
"expiry_date": "2026-10-01"
}'成功响应(列表类似,含 quotes/invoices 及 total/page/limit/has_more):
// Wrapped envelope (POST/PATCH/lists): { success:true, data:{ quote } }
{
"success": true,
"data": {
"quote": { "id": "uuid", "quote_number": "Q-1001", "total": 528.0 }
}
}curl -X PATCH https://simplyquote.net/api/v1/invoices/{id} \
-H "Authorization: Bearer sq_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "status": "paid" }'列表查询与分页
列表端点支持 updated_since(ISO 8601)、page(默认 1)、limit(默认 20,最大 100)和 status(不区分大小写,未知值会被忽略)。响应包含 total、page、limit 和 has_more。
GET /api/v1/quotes?status=sent&page=1&limit=20&updated_since=2026-01-01T00:00:00Z
创建与更新的字段规则
POST 时 items 必填:非空数组,每行必须有非空 description、quantity > 0(默认 1)、unit_price >= 0(默认 0)。tax_rate 为百分比(0–100);创建时 tax_rate > 0 即表示 tax_enabled。currency 会转为大写存储。issue_date 接受任何可解析日期(按 YYYY-MM-DD 存储)。报价单使用 expiry_date,发票使用 due_date(两个别名都可接受,null 表示清空)。状态:报价单 draft|sent,发票 draft|sent|viewed|paid|cancelled——设为 paid 会记录 paid_at。总额始终由服务器重新计算。
4. 与 AI 代理配合使用
把基础 URL、您的令牌和下面的端点列表告诉您的代理。适用于任何支持工具调用的代理(Claude、GPT、LangChain 等)的示例指令:
你可以访问我的 SimplyQuote 账户。
基础 URL: https://simplyquote.net
每个请求都要发送请求头: Authorization: Bearer sq_你的令牌
可用端点: GET/POST /api/v1/quotes、GET/PATCH /api/v1/quotes/{id}、
GET/POST /api/v1/invoices、GET/PATCH /api/v1/invoices/{id}、POST /api/mcp
列表支持 ?page、?limit(最大 100)、?status、?updated_since,返回 { success:true, data:{ quotes|invoices, total, page, limit, has_more } }。
单据查询直接返回裸对象。{id} 是 UUID,不是单据编号。
创建文档请使用 POST——items 中必须包含 description、quantity 和 unit_price。5. 通过 MCP 连接(推荐给代理使用)
SimplyQuote 在 /api/mcp 内置了 MCP(Model Context Protocol)服务器(无状态 streamable HTTP,JSON-RPC 2.0)。支持远程 MCP 服务器的代理(Claude、ChatGPT、Cursor、VS Code 等)只需您的令牌即可直接连接,无需提示词工程。可用工具:
list_quotesget_quotecreate_quotelist_invoicesget_invoicecreate_invoice
{
"mcpServers": {
"simplyquote": {
"type": "http",
"url": "https://simplyquote.net/api/mcp",
"headers": {
"Authorization": "Bearer sq_your_token_here"
}
}
}
}工具调用示例(JSON-RPC 2.0——不支持批量请求,通知返回 202,GET 返回 405):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "list_quotes", "arguments": { "limit": 5 } }
}每次工具调用都会根据您令牌的范围进行校验——只读令牌可以列表和查询,而创建报价单或发票需要相应的写范围。
端点
| 方法 | 路径 | 所需范围 | 说明 |
|---|---|---|---|
| GET | /api/v1/quotes | quotes:read | 列出报价单 |
| GET | /api/v1/quotes/{id} | quotes:read | 获取单个报价单 |
| POST | /api/v1/quotes | quotes:write | 创建报价单(总额由服务器计算) |
| PATCH | /api/v1/quotes/{id} | quotes:write | 更新报价单(状态: draft | sent) |
| GET | /api/v1/invoices | invoices:read | 列出发票 |
| GET | /api/v1/invoices/{id} | invoices:read | 获取单张发票 |
| POST | /api/v1/invoices | invoices:write | 创建发票(总额由服务器计算) |
| PATCH | /api/v1/invoices/{id} | invoices:write | 更新发票(状态: draft | sent | viewed | paid | cancelled) |
| GET | /api/v1/webhooks | any valid token | 列出 Webhook 订阅 |
| POST | /api/v1/webhooks | any valid token | 创建 Webhook(密钥仅显示一次) |
| PATCH | /api/v1/webhooks | any valid token | 更新 Webhook |
| DELETE | /api/v1/webhooks?id= | any valid token | 删除 Webhook(?id=) |
| GET | /api/v1/openapi.json | none | 机器可读的 OpenAPI 规范 |
| POST | /api/mcp | per-tool | 面向 AI 代理的 MCP 服务器(JSON-RPC 2.0) |
范围
quotes:read— 读取您的报价单invoices:read— 读取您的发票clients:read— 保留中——暂无独立的客户端点(客户信息包含在报价单/发票中)quotes:write— 创建和更新报价单invoices:write— 创建和更新发票clients:write— 保留中——暂无独立的客户端点(保存报价单/发票时客户信息会被隐式创建/更新)
响应格式与错误
REST 端点使用两种格式,请确认当前适用哪一种:
{
"success": true,
"data": { ... },
"error": { "code": "...", "message": "...", "details": { ... } }
}单据查询直接返回上面的裸对象(无包装),错误为扁平的 { error, message }(如未知 id 时返回 404)。列表以及 POST/PATCH 始终使用包装结构。
// Flat envelope (single GET): bare object, no success/data wrapper
{
"id": "uuid",
"quote_number": "Q-1001",
"status": "sent",
"total": 528.0
}
// unknown id:
{ "error": "not_found", "message": "Quote not found" }success— 成功为 true,失败为 falsedata— 成功时的数据error— 失败时的错误代码、消息和可选详情
最常见的错误代码:
UNAUTHORIZED— 令牌缺失、无效或已过期(HTTP 401)FORBIDDEN— 令牌没有所需范围(HTTP 403)VALIDATION_ERROR— 请求体未通过验证(HTTP 400)NOT_FOUND— 请求的文档不存在(HTTP 404)DATABASE_ERROR— 处理请求时发生存储错误(HTTP 500)RATE_LIMIT— 请求过多——请稍后重试(HTTP 429)
Webhook、OAuth 与完整参考
Webhook:通过 GET/POST/PATCH/DELETE /api/v1/webhooks 管理订阅(任何有效令牌即可,无需特定范围)。url 必须是公开 HTTPS 端点。密钥仅在创建时返回——请通过 X-SimplyQuote-Signature(HMAC-SHA256)请求头验证推送。
合作应用使用 OAuth 2.0(/api/oauth/authorize、/api/oauth/token、/api/oauth/revoke)而非个人令牌。详情见 docs/API.md,以及 /api/v1/openapi.json 上的机器可读规范。
安全须知
- 令牌以哈希形式存储——SimplyQuote 绝不保留原始令牌。
- 只授予您的代理所需范围;通常只读范围就足够了。
- 随时可在设置中撤销令牌,立即切断访问。
- 面向代理的机器可读规范位于
/api/v1/openapi.json