API 密钥
创建、查看、轮换和撤销用于程序访问的 API 密钥,并读取其用量分析数据。
集成通过 API 密钥向 Warmbly API 进行身份验证。每个密钥都属于某个组织,携带限定其可执行操作的权限位掩码,并可限制为仅允许特定来源 IP 或特定邮箱。本组接口支持自助管理:持有 API_KEYS 权限范围的密钥可直接管理所属组织的密钥,无需通过控制台,因此集成可以用程序轮换自身凭据。
本组所有端点均要求:API 密钥调用者具有 权限范围 API_KEYS,会话或 JWT 调用者具有 组织权限 manage_api_keys。所有路由均限定在组织范围内,并受写入速率限制。
权限位掩码
密钥的 permissions 字段是一个 uint64 位掩码。每项授权对应一个位;只有掩码包含路由要求的所有位时,密钥才可执行请求。通过按位 OR 组合权限位。完整的权限位名称和值,以及 read_only 和 full_access 预设,可从下方权限端点获取,也在 API 权限中说明。创建时会拒绝未知权限位,防止旧客户端意外授予未来新增的权限范围。
明文密钥仅显示一次
创建密钥时,响应的 secret 字段包含完整明文密钥。这是唯一一次返回机密值。Warmbly 仅保存哈希,以及用于显示的短前缀和后缀,因此之后无法恢复明文。应在创建时保存并妥善保管。如果丢失,应撤销该密钥并创建新密钥。请求中如何传入密钥见身份验证。
列出 API 密钥
GET /api-keys
返回组织的 API 密钥,按最新优先排序,始终不包含机密值。
status 为 active 或 revoked。过期判断在读取密钥时应用,不会写入记录,因此超过 expires_at 的密钥在这里仍显示为 active,但已经无法用于任何身份验证。如果需要判断密钥是否可用,应将 expires_at 与当前时间比较。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
cursor | query | string | 上一页 pagination.next_cursor 中的不透明游标。第一页省略。 |
limit | query | integer | 每页数量,范围 1 至 100,默认 50。超出范围或无效的值会回退到默认值。 |
响应
data 加 pagination 响应封装。每项为不包含机密值的 API 密钥。
{
"data": [
{
"id": "0b2d5e7a-1c3f-4a9b-8c2d-1e2f3a4b5c6d",
"user_id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Zapier production",
"description": "Lead sync from the marketing site",
"key_prefix": "wmbly_3f",
"key_suffix": "9f3a",
"permissions": 8447,
"allowed_ips": ["203.0.113.10"],
"allowed_email_accounts": [],
"rate_limit_per_minute": 120,
"status": "active",
"last_used_at": "2026-06-11T18:42:10Z",
"last_request_ip": "203.0.113.10",
"expires_at": null,
"created_at": "2026-05-01T09:00:00Z",
"updated_at": "2026-06-11T18:42:10Z"
}
],
"pagination": {
"total": null,
"next_cursor": "c1_b3BhcXVlLWN1cnNvcg",
"has_more": true
}
}创建 API 密钥
POST /api-keys
创建新密钥,并且仅返回一次明文机密值,详见上方说明。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 便于识别的标签,最长 255 个字符。 |
description | string | 否 | 用于说明密钥用途的自由格式备注。 |
permissions | integer (uint64) | 是 | 权限位掩码。只能包含已定义的位,未知位会被拒绝。 |
allowed_ips | string array | 否 | 设置后,仅允许从这些来源 IP 使用密钥。省略或留空表示允许任意 IP。 |
allowed_email_accounts | uuid array | 否 | 设置后,按邮箱限定的路由仅接受这些邮箱账户 ID。 |
rate_limit_per_minute | integer | 否 | 每个密钥的滑动窗口请求上限。省略或发送 0 使用默认值,即每分钟 60 次。 |
expires_at | string (RFC3339) | 否 | 密钥停止生效的时间。省略则创建永不过期的密钥。 |
{
"name": "Zapier production",
"description": "Lead sync from the marketing site",
"permissions": 8447,
"allowed_ips": ["203.0.113.10"],
"rate_limit_per_minute": 120,
"expires_at": "2027-01-01T00:00:00Z"
}响应
201 Created。完整密钥对象,加上仅返回一次的 secret。除 secret 外,所有字段均与列表及获取端点的响应结构一致。
{
"id": "0b2d5e7a-1c3f-4a9b-8c2d-1e2f3a4b5c6d",
"user_id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Zapier production",
"description": "Lead sync from the marketing site",
"key_prefix": "wmbly_3f",
"key_suffix": "9f3a",
"permissions": 8447,
"allowed_ips": ["203.0.113.10"],
"rate_limit_per_minute": 120,
"status": "active",
"expires_at": "2027-01-01T00:00:00Z",
"created_at": "2026-06-11T19:00:00Z",
"updated_at": "2026-06-11T19:00:00Z",
"secret": "wmbly_3f9a...the-only-time-you-see-this...9f3a"
}此端点会修改状态,支持 Idempotency-Key,可安全重试。
列出可用权限
GET /api-keys/permissions
返回权限位目录和内置预设,便于客户端显示选择器或授予合理的默认权限,无需硬编码数值。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
响应
对象包含 permissions 数组,其中每项带有 name、数字形式的 value、description,以及取值为 read、write、bulk 或 special 的 category;另有 presets 对象,包含 read_only 和 full_access 掩码。
{
"permissions": [
{
"name": "READ_EMAILS",
"value": 1,
"description": "View email accounts and settings",
"category": "read"
},
{
"name": "WRITE_CAMPAIGNS",
"value": 64,
"description": "Create and modify campaigns and sequences",
"category": "write"
}
// ... one entry per defined permission bit
],
"presets": {
"read_only": 4329731,
"full_access": 8388607
}
}获取 API 密钥
GET /api-keys/:id
按 ID 返回单个密钥,始终不包含机密值。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | API 密钥 ID。 |
响应
密钥对象,结构与列表响应 data 数组中的单个元素相同。
{
"id": "0b2d5e7a-1c3f-4a9b-8c2d-1e2f3a4b5c6d",
"user_id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Zapier production",
"description": "Lead sync from the marketing site",
"key_prefix": "wmbly_3f",
"key_suffix": "9f3a",
"permissions": 8447,
"allowed_ips": ["203.0.113.10"],
"rate_limit_per_minute": 120,
"status": "active",
"last_used_at": "2026-06-11T18:42:10Z",
"last_request_ip": "203.0.113.10",
"expires_at": null,
"created_at": "2026-05-01T09:00:00Z",
"updated_at": "2026-06-11T18:42:10Z"
}更新 API 密钥
PATCH /api-keys/:id
更新密钥的可变字段。所有字段均可选,只修改实际发送的字段。不能在此轮换机密值,应创建新密钥并撤销旧密钥。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | API 密钥 ID。 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 否 | 新标签。 |
description | string | 否 | 新说明。 |
permissions | integer (uint64) | 否 | 替换现有权限位掩码。 |
allowed_ips | string array | 否 | 替换现有 IP 允许列表。 |
allowed_email_accounts | uuid array | 否 | 替换现有邮箱允许列表。 |
rate_limit_per_minute | integer | 否 | 新的密钥速率上限,0 表示使用默认值。 |
{
"description": "Lead sync, now read-only",
"permissions": 4329731,
"rate_limit_per_minute": 60
}响应
更新后的密钥对象,结构与获取响应相同。
{
"id": "0b2d5e7a-1c3f-4a9b-8c2d-1e2f3a4b5c6d",
"name": "Zapier production",
"description": "Lead sync, now read-only",
"permissions": 4329731,
"rate_limit_per_minute": 60,
"status": "active",
"updated_at": "2026-06-11T19:30:00Z"
// ... remaining key fields unchanged
}撤销 API 密钥
DELETE /api-keys/:id
立即撤销密钥。密钥会立刻停止用于身份验证;此操作不可逆。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | API 密钥 ID。 |
reason | query | string | 可选的撤销备注,会保存在密钥记录中。默认为 Revoked by user。 |
响应
简短的状态响应封装。
{ "status": "revoked" }删除 API 密钥
DELETE /api-keys/:id/permanent
从工作区永久移除已撤销或已过期的密钥,以及其用量日志。如果密钥仍可用于身份验证,会返回 409 并拒绝删除:应先撤销,以便保留凭据失效原因的记录。超过 expires_at 的密钥可直接删除,因为它已无法用于任何身份验证。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | API 密钥 ID。 |
响应
简短的状态响应封装。
{ "status": "deleted" }用量摘要
GET /api-keys/usage/summary
返回组织级用量摘要:按状态统计的密钥数量,以及最近 24 小时的请求、错误和延迟汇总。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
响应
单个摘要对象。24h 字段中的计数覆盖最近 24 小时。
{
"active_keys": 3,
"revoked_keys": 1,
"expired_keys": 0,
"requests_24h": 14820,
"errors_24h": 37,
"avg_latency_ms_24h": 42.6,
"last_call_at": "2026-06-11T18:42:10Z"
}用量分析
GET /api-keys/usage/analytics
GET /api-keys/:id/analytics
返回按时间桶聚合的请求序列,以及按端点划分的明细。两个路由共用同一处理程序:组织级路径为 /api-keys/usage/analytics,单个密钥路径为 /api-keys/:id/analytics。也可在单个密钥路由中,将 :id 设为字面值 all,获取组织级汇总。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | API 密钥 ID,或用于组织级汇总的字面值 all,仅适用于单个密钥路由。 |
from | query | string (RFC3339) | 时间窗口起点。默认为 to 前 24 小时。 |
to | query | string (RFC3339) | 时间窗口终点。默认为当前时间。 |
interval | query | string | 时间桶粒度:minute、hour 或 day。 |
响应
分析对象:buckets 为图表序列,endpoints 为热门端点表,total / errors 为时间窗口内的总数。对于组织级汇总,api_key_id 为全零 UUID。
{
"api_key_id": "0b2d5e7a-1c3f-4a9b-8c2d-1e2f3a4b5c6d",
"from": "2026-06-10T19:00:00Z",
"to": "2026-06-11T19:00:00Z",
"interval": "hour",
"buckets": [
{
"bucket": "2026-06-11T18:00:00Z",
"total": 612,
"success": 605,
"client_errors": 6,
"server_errors": 1,
"avg_latency_ms": 41.2
}
// ... one bucket per interval
],
"endpoints": [
{
"endpoint": "/v1/contacts",
"method": "POST",
"count": 980,
"error_count": 4,
"avg_latency_ms": 55.1
}
],
"total": 14820,
"errors": 37
}列出指定密钥的用量日志
GET /api-keys/:id/logs
返回单个密钥最近的原始请求记录,按最新优先排序。可用于排查该密钥发起过哪些请求,以及各请求的响应情况。
身份验证:权限范围 API_KEYS · 组织权限 manage_api_keys
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | API 密钥 ID。 |
cursor | query | string | 上一页 pagination.next_cursor 中的不透明游标。 |
limit | query | integer | 每页数量,范围 1 至 200,默认 50。 |
响应
data 加 pagination 响应封装。每项对应一条已记录的请求。
{
"data": [
{
"id": "7c1f9a2b-3d4e-5f60-7a8b-9c0d1e2f3a4b",
"api_key_id": "0b2d5e7a-1c3f-4a9b-8c2d-1e2f3a4b5c6d",
"endpoint": "/v1/contacts",
"method": "POST",
"ip_address": "203.0.113.10",
"user_agent": "warmbly-zapier/1.4",
"response_code": 201,
"response_time_ms": 48,
"created_at": "2026-06-11T18:42:10Z"
}
],
"pagination": {
"total": null,
"next_cursor": "c1_b3BhcXVlLWN1cnNvcg",
"has_more": true
}
}错误
所有端点均使用共享错误响应封装,包含稳定的 code 和 request_id 字段。本组接口的常见情况包括:
400:未选择组织、请求体无效,或权限位掩码包含未知位。401:调用者未通过身份验证。403:调用者缺少API_KEYS权限范围或manage_api_keys组织权限。404::id路径值不是有效 UUID,或密钥不属于该组织。409:尝试删除仍可用于身份验证的密钥。请先撤销。
完整列表见错误码。