名称:api-portal-design
描述:API文档和开发者门户设计
允许的工具:读取、全局查找、搜索、写入、编辑
API门户设计技能
何时使用此技能
在以下情况下使用此技能:
- API门户设计任务 - 处理API文档和开发者门户设计
- 规划或设计 - 需要API门户设计方法的指导
- 最佳实践 - 希望遵循既定模式和标准
概述
设计全面的API文档和开发者门户,以提供卓越的开发者体验。
强制要求:文档优先方法
在设计API门户之前:
- 调用
docs-management技能获取API文档模式
- 通过MCP服务器验证OpenAPI/AsyncAPI标准(上下文7)
- 基于行业API文档最佳实践提供指导
开发者门户架构
开发者门户组件:
┌─────────────────────────────────────────────────────────────────────────────┐
│ 开发者门户 │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 入门指南 │ │ API参考 │ │ 代码示例 │ │ API控制台 │ │
│ │ Getting │ │ API │ │ Code │ │ API │ │
│ │ Started │ │ Reference │ │ Examples │ │ Console │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ SDK和库 │ │ 变更日志 │ │ 状态页面 │ │ 支持中心 │ │
│ │ SDKs & │ │ Change │ │ Status │ │ Support │ │
│ │ Libraries │ │ Log │ │ Page │ │ Center │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 认证和API密钥 │ │
│ │ Authentication & API Keys │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
门户内容结构
必备部分
| 部分 |
目的 |
优先级 |
| 入门指南 |
首次用户指南 |
P0 |
| 认证 |
如何进行认证 |
P0 |
| API参考 |
完整端点文档 |
P0 |
| 代码示例 |
可复制的样本 |
P0 |
| SDK |
客户端库 |
P1 |
| 变更日志 |
版本历史 |
P1 |
| 速率限制 |
使用限制 |
P1 |
| 错误 |
错误处理指南 |
P1 |
| Webhooks |
事件通知 |
P2 |
| 最佳实践 |
使用建议 |
P2 |
入门指南
# 入门指南
在5分钟内启动并运行[产品]API。
## 前提条件
- 在[产品]上拥有账户([免费注册](链接))
- API密钥([获取密钥](链接))
- REST API的基础知识
## 快速入门
### 1. 获取您的API密钥
1. 登录到[产品]仪表板
2. 导航到**设置 → API密钥**
3. 点击**创建新密钥**
4. 复制您的密钥(您将无法再次查看!)
### 2. 发出第一个请求
```bash
curl -X GET "https://api.example.com/v1/users/me" \
-H "Authorization: Bearer 您的API密钥"
响应:
{
"id": "usr_123abc",
"email": "developer@example.com",
"name": "Jane Developer",
"created_at": "2025-01-15T10:30:00Z"
}
3. 探索API
后续步骤
需要帮助?
认证文档
# 认证
所有API请求都需要使用Bearer令牌进行认证。
## API密钥
API密钥是用于服务器到服务器通信的长期凭证。
### 创建API密钥
1. 转到**仪表板 → 设置 → API密钥**
2. 点击**创建新密钥**
3. 给它一个描述性名称
4. 选择适当的权限
5. 复制并安全存储密钥
### 使用API密钥
在`Authorization`头中包含您的API密钥:
```bash
curl -X GET "https://api.example.com/v1/resource" \
-H "Authorization: Bearer 您的API密钥"
密钥安全最佳实践
| 做 |
不做 |
| 将密钥存储在环境变量中 |
将密钥提交到源代码控制 |
| 为每个环境使用单独的密钥 |
在服务之间共享密钥 |
| 定期轮换密钥 |
在客户端代码中使用密钥 |
| 设置最低所需权限 |
为所有操作使用管理员密钥 |
OAuth 2.0
对于面向用户的应用程序,使用OAuth 2.0进行安全的委托访问。
授权码流程
┌──────────┐ ┌──────────┐
│ 客户端应用 │ │ 认证服务器 │
│ Client │ │ Auth │
│ App │ │ Server │
└────┬─────┘ └────┬─────┘
│ │
│ 1. 重定向到授权端点 │
│─────────────────────────────────────────►│
│ │
│ 2. 用户认证并同意 │
│ │
│ 3. 重定向回授权码 │
│◄─────────────────────────────────────────│
│ │
│ 4. 交换令牌 │
│─────────────────────────────────────────►│
│ │
│ 5. 返回访问令牌和刷新令牌 │
│◄─────────────────────────────────────────│
│ │
OAuth端点
| 端点 |
URL |
| 授权 |
https://auth.example.com/oauth/authorize |
| 令牌 |
https://auth.example.com/oauth/token |
| 撤销 |
https://auth.example.com/oauth/revoke |
范围
| 范围 |
描述 |
read:users |
读取用户信息 |
write:users |
创建和更新用户 |
read:orders |
读取订单数据 |
write:orders |
创建和修改订单 |
令牌刷新
curl -X POST "https://auth.example.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=您的刷新令牌" \
-d "client_id=您的客户端ID" \
-d "client_secret=您的客户端密钥"
OpenAPI规范模板
openapi: 3.1.0
info:
title: 产品API
version: 1.0.0
description: |
产品API提供对[产品]功能的编程访问。
## 认证
所有端点都需要通过Bearer令牌进行认证。
从[仪表板](https://dashboard.example.com)获取您的API密钥。
## 速率限制
- 标准:每分钟100个请求
- 高级:每分钟1000个请求
详情见[速率限制](/docs/rate-limits)。
contact:
name: API支持
email: api-support@example.com
url: https://example.com/support
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://api.example.com/v1
description: 生产环境
- url: https://api-staging.example.com/v1
description: 预生产环境
security:
- bearerAuth: []
tags:
- name: 用户
description: 用户管理操作
- name: 订单
description: 订单处理操作
paths:
/users:
get:
tags: [用户]
operationId: listUsers
summary: 列出所有用户
description: |
返回您组织中分页的用户列表。
结果按创建日期排序,最新的在前。
parameters:
- name: limit
in: query
description: 返回的最大结果数
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: cursor
in: query
description: 从前一个响应中的分页游标
schema:
type: string
responses:
'200':
description: 成功响应
content:
application/json:
schema:
$ref: '#/components/schemas/UserList'
examples:
default:
summary: 示例响应
value:
data:
- id: "usr_123"
email: "jane@example.com"
name: "Jane Doe"
created_at: "2025-01-15T10:30:00Z"
has_more: true
next_cursor: "cur_abc123"
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimited'
post:
tags: [用户]
operationId: createUser
summary: 创建用户
description: 在您的组织中创建新用户。
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
examples:
basic:
summary: 基本用户创建
value:
email: "jane@example.com"
name: "Jane Doe"
with_metadata:
summary: 带元数据的用户
value:
email: "jane@example.com"
name: "Jane Doe"
metadata:
department: "工程部"
role: "开发者"
responses:
'201':
description: 用户已创建
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'409':
description: 用户已存在
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/users/{userId}:
get:
tags: [用户]
operationId: getUser
summary: 获取用户
description: 通过ID检索用户。
parameters:
- name: userId
in: path
required: true
description: 用户的唯一标识符
schema:
type: string
pattern: '^usr_[a-zA-Z0-9]+$'
example: usr_123abc
responses:
'200':
description: 成功响应
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
使用您的API密钥作为Bearer令牌。
示例:`Authorization: Bearer sk_live_abc123`
schemas:
User:
type: object
required: [id, email, created_at]
properties:
id:
type: string
description: 用户的唯一标识符
example: usr_123abc
email:
type: string
format: email
description: 用户的电子邮件地址
example: jane@example.com
name:
type: string
description: 用户的显示名称
example: Jane Doe
created_at:
type: string
format: date-time
description: 用户创建时间
example: "2025-01-15T10:30:00Z"
metadata:
type: object
additionalProperties: true
description: 自定义键值对
UserList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
has_more:
type: boolean
description: 是否有更多结果可用
next_cursor:
type: string
description: 用于获取下一页的游标
CreateUserRequest:
type: object
required: [email]
properties:
email:
type: string
format: email
name:
type: string
metadata:
type: object
additionalProperties: true
Error:
type: object
required: [error]
properties:
error:
type: object
required: [code, message]
properties:
code:
type: string
description: 错误代码
example: invalid_request
message:
type: string
description: 人类可读的错误消息
example: 电子邮件字段是必需的
details:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
responses:
BadRequest:
description: 无效请求
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: invalid_request
message: 验证失败
details:
- field: email
message: 无效的电子邮件格式
Unauthorized:
description: 需要认证
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: unauthorized
message: 无效或缺少API密钥
NotFound:
description: 资源未找到
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: not_found
message: 用户未找到
RateLimited:
description: 超出速率限制
headers:
X-RateLimit-Limit:
schema:
type: integer
description: 每分钟请求限制
X-RateLimit-Remaining:
schema:
type: integer
description: 当前窗口中剩余的请求
X-RateLimit-Reset:
schema:
type: integer
description: 限制重置的Unix时间戳
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: rate_limited
message: 请求过多。请在60秒后重试。
错误文档
# 错误处理
API使用常规HTTP响应代码并返回详细的错误信息。
## HTTP状态代码
| 代码 | 含义 |
|------|---------|
| 200 | 成功 |
| 201 | 已创建 |
| 204 | 无内容 |
| 400 | 错误请求 - 无效参数 |
| 401 | 未授权 - 无效或缺少凭证 |
| 403 | 禁止 - 权限不足 |
| 404 | 未找到 - 资源不存在 |
| 409 | 冲突 - 资源已存在 |
| 422 | 不可处理 - 验证失败 |
| 429 | 请求过多 - 速率限制 |
| 500 | 内部错误 - 服务器端问题 |
## 错误响应格式
```json
{
"error": {
"code": "invalid_request",
"message": "电子邮件字段是必需的",
"request_id": "req_abc123",
"details": [
{
"field": "email",
"message": "此字段是必需的"
}
]
}
}
错误代码参考
认证错误
| 代码 |
描述 |
解决方案 |
unauthorized |
缺少或无效的API密钥 |
检查API密钥是否正确 |
token_expired |
访问令牌已过期 |
刷新您的令牌 |
insufficient_scope |
令牌缺少所需范围 |
请求额外范围 |
验证错误
| 代码 |
描述 |
解决方案 |
invalid_request |
请求体格式错误 |
检查JSON语法 |
validation_failed |
一个或多个字段无效 |
见details数组 |
missing_required_field |
未提供必需字段 |
包括所有必需字段 |
资源错误
| 代码 |
描述 |
解决方案 |
not_found |
资源不存在 |
验证ID是否正确 |
already_exists |
资源已存在 |
使用现有资源或更改标识符 |
resource_locked |
资源正在修改 |
短暂延迟后重试 |
在代码中处理错误
C#
try
{
var user = await client.Users.GetAsync(userId, ct);
}
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
_logger.LogWarning("用户 {UserId} 未找到", userId);
return NotFound();
}
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.TooManyRequests)
{
var retryAfter = ex.Headers.RetryAfter?.Delta ?? TimeSpan.FromSeconds(60);
await Task.Delay(retryAfter, ct);
// 重试请求
}
catch (ApiException ex)
{
_logger.LogError(ex, "API错误: {Code} - {Message}", ex.Error.Code, ex.Error.Message);
throw;
}
TypeScript
try {
const user = await client.users.get(userId);
} catch (error) {
if (error instanceof ApiError) {
switch (error.code) {
case 'not_found':
console.warn(`用户 ${userId} 未找到`);
return null;
case 'rate_limited':
await sleep(error.retryAfter ?? 60000);
return client.users.get(userId); // 重试
default:
console.error(`API错误: ${error.code} - ${error.message}`);
throw error;
}
}
throw error;
}
代码示例部分
# 代码示例
热门语言中的即用示例。
## 创建用户
### cURL
```bash
curl -X POST "https://api.example.com/v1/users" \
-H "Authorization: Bearer 您的API密钥" \
-H "Content-Type: application/json" \
-d '{
"email": "jane@example.com",
"name": "Jane Doe"
}'
C# (.NET)
using var client = new ProductApiClient(apiKey);
var user = await client.Users.CreateAsync(new CreateUserRequest
{
Email = "jane@example.com",
Name = "Jane Doe"
});
Console.WriteLine($"创建用户: {user.Id}");
TypeScript
import { ProductApi } from '@example/sdk';
const client = new ProductApi({ apiKey: process.env.API_KEY });
const user = await client.users.create({
email: 'jane@example.com',
name: 'Jane Doe',
});
console.log(`创建用户: ${user.id}`);
Python
from example_sdk import ProductApi
client = ProductApi(api_key=os.environ["API_KEY"])
user = client.users.create(
email="jane@example.com",
name="Jane Doe"
)
print(f"创建用户: {user.id}")
门户工具选项
| 工具 |
类型 |
最适合 |
| Stoplight |
托管 |
设计优先,协作 |
| Redocly |
托管/自托管 |
OpenAPI渲染 |
| ReadMe |
托管 |
完整门户,交互式 |
| SwaggerHub |
托管 |
Swagger生态系统 |
| Scalar |
开源 |
现代,可定制 |
| Docusaurus + 插件 |
开源 |
完全控制 |
最佳实践
开发者体验原则
| 原则 |
实现 |
| 首次调用时间 |
最小化首次API调用的步骤 |
| 可复制粘贴 |
所有示例应立即可用 |
| 错误消息 |
清晰、可操作的错误响应 |
| 一致性 |
所有端点使用相同模式 |
| 可发现性 |
易于查找和导航 |
文档质量检查表
- [ ] 每个端点都有描述和示例
- [ ] 所有参数都记录了类型和约束
- [ ] 响应模式完全文档化
- [ ] 错误代码有解释和解决方案
- [ ] 认证清晰解释
- [ ] 速率限制文档化
- [ ] 多种语言的代码示例
- [ ] 入门指南不超过5分钟
工作流程
设计API门户时:
- 定义受众:谁将使用API?
- 结构化内容:按用户旅程组织
- 编写OpenAPI规范:完整的规范
- 添加示例:目标语言中的工作代码
- 构建门户:选择工具,实施
- 用户测试:验证首次调用时间
- 迭代:基于反馈改进
参考
详细指导:
最后更新: 2025-12-26