| name | api-development |
| description | FastGPT API 开发规范。重点强调使用 zod schema 定义入参和出参,在 API 文档中声明路由信息,编写对应的 OpenAPI 文档,以及在 API 路由中使用 schema.parse 进行验证。 |
FastGPT API 开发规范
FastGPT 项目 API 路由开发的标准化指南,确保 API 的一致性、类型安全和文档完整性。
何时使用此技能
- 开发新的 Next.js API 路由
- 修改现有 API 的入参或出参
- 需要 API 类型定义和文档
- 审查 API 相关代码
核心原则
🔴 必须遵守的规则
- 所有 API 必须使用 zod schema 定义入参和出参
- 必须导出 schema 的 TypeScript 类型
- 必须在 schema 文件头部声明 API 信息(路由、方法、描述、标签),一次性管理员升级/清洗能力除外
- 入参必须使用 schema.parse() 验证
- 函数返回值必须使用 schema.parse() 验证
- 必须编写完整的 OpenAPI 文档,一次性管理员升级/清洗能力除外
管理员升级与清洗能力的文档豁免
仅供系统管理员执行、用于一次性升级、迁移、修复或数据清洗的内部接口和脚本,不属于产品 API,不要求:
- 在
packages/global/openapi/ 声明接口文档;
- 注册 OpenAPI Path;
- 编写 API 头部路由、方法、描述和标签信息。
豁免只针对文档,不豁免安全和校验要求:
- 管理员接口必须使用
authSystemAdmin 鉴权;
- API 入参必须使用 Zod Schema 和
parseApiInput;
- 返回值必须使用 Zod Schema 校验,空成功响应使用
z.undefined();
- 数据清洗默认使用 dry-run,显式确认后才能写入,并输出成功、跳过和失败统计;
- 清洗逻辑应可重复执行,无法安全修复的数据必须跳过并报告,不得静默填入猜测值。
常规管理员产品接口(例如模型配置 CRUD、用户管理和系统配置)不因仅管理员可用而获得豁免,仍需按标准 API 流程维护文档。
开发流程
步骤 1: 定义 Zod Schema 并声明 API
文件位置: packages/global/openapi/[module]/[api].ts
文件头部必须声明 API 信息:
import { z } from 'zod';
export const GetAppChatLogsBodySchema = PaginationSchema.extend({
appId: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '应用 ID'
}),
dateStart: z.union([z.string(), z.date()]).meta({
example: '2024-01-01T00:00:00.000Z',
description: '开始时间'
}),
dateEnd: z.union([z.string(), z.date()]).meta({
example: '2024-12-31T23:59:59.999Z',
description: '结束时间'
}),
sources: z.array(z.nativeEnum(ChatSourceEnum)).optional().meta({
example: [ChatSourceEnum.api, ChatSourceEnum.online],
description: '对话来源筛选'
})
});
export type getAppChatLogsBody = z.infer<typeof GetAppChatLogsBodySchema>;
export const GetAppChatLogsResponseSchema = z.object({
total: z.number().meta({ example: 100, description: '总记录数' }),
list: z.array(ChatLogItemSchema)
});
export type getAppChatLogsResponseType = z.infer<typeof GetAppChatLogsResponseSchema>;
API 声明规范:
OpenAPI Tag 归属规则:
- 如果接口能力属于通用模块 A,但会被业务模块 B 使用,则该接口必须同时声明 A 模块 tag 和 B 模块 tag。
- 如果同一个通用接口也被业务模块 C 使用,则继续追加 C 模块 tag。
- 通用模块 tag 表示接口能力和实现抽象归属;业务模块 tag 表示该接口应出现在对应业务文档视角里。
- 如果接口只是业务模块自己的状态查询或状态操作,不属于通用模块能力,则只声明业务模块 tag,不要为了实现位置或相邻目录误加通用模块 tag。
- 示例:
协作者管理 是通用权限能力,应用协作者接口需要同时声明 协作者管理 和应用侧 权限管理;获取应用权限、恢复应用继承权限 是应用自身权限状态接口,只声明应用侧 权限管理。
Schema 定义规范:
✅ 字段定义规范
export const GetUserSchema = z.object({
userId: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '用户 ID'
}),
email: z.string().email().meta({
example: 'user@example.com',
description: '用户邮箱'
}),
age: z.number().int().positive().meta({
example: 25,
description: '用户年龄'
}),
status: z.enum(['active', 'inactive']).meta({
example: 'active',
description: '用户状态'
})
});
export const GetUserSchemaBad = z.object({
userId: z.string(),
email: z.string(),
age: z.number(),
status: z.string()
});
✅ 嵌套对象定义
export const AddressSchema = z.object({
street: z.string().meta({ description: '街道地址' }),
city: z.string().meta({ description: '城市' }),
country: z.string().meta({ description: '国家' })
});
export const CreateUserSchema = z.object({
name: z.string().meta({ description: '用户名' }),
address: AddressSchema.meta({ description: '地址信息' })
});
✅ 数组定义
export const GetUserListResponseSchema = z.object({
total: z.number().meta({ example: 100, description: '总数' }),
list: z.array(
z.object({
id: z.string().meta({ description: '用户 ID' }),
name: z.string().meta({ description: '用户名' })
})
).meta({ description: '用户列表' })
});
✅ 可选字段
export const UpdateUserSchema = z.object({
userId: z.string().meta({ description: '用户 ID' }),
name: z.string().optional().meta({ description: '用户名' }),
email: z.string().email().nullish().meta({ description: '用户邮箱' })
});
✅ 分页 Schema
import { PaginationSchema } from '@fastgpt/global/openapi/api';
export const GetUserListSchema = PaginationSchema.extend({
keyword: z.string().optional().meta({ description: '搜索关键词' }),
status: z.enum(['active', 'inactive']).optional().meta({ description: '状态筛选' })
});
✅ 多个 API 的 Schema 文件
export const GetLogKeysQuerySchema = z.object({
appId: z.string().meta({ description: '应用 ID' })
});
export const GetLogKeysResponseSchema = z.object({
logKeys: z.array(AppLogKeysSchema).meta({ description: '日志键列表' })
});
export const UpdateLogKeysBodySchema = z.object({
appId: z.string().meta({ description: '应用 ID' }),
logKeys: z.array(AppLogKeysSchema).meta({ description: '日志键列表' })
});
步骤 2: 实现 API 路由
文件位置: projects/app/src/pages/api/[path]/[route].ts
标准实现模板:
import type { NextApiResponse } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import type { ApiRequestProps } from '@fastgpt/service/types/next';
import {
GetAppChatLogsBodySchema,
GetAppChatLogsResponseSchema,
type getAppChatLogsResponseType
} from '@fastgpt/global/openapi/...';
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<getAppChatLogsResponseType> {
const { appId, dateStart, dateEnd, sources } = GetAppChatLogsBodySchema.parse(req.body);
const result = await yourBusinessLogic({ appId, dateStart, dateEnd, sources });
return GetAppChatLogsResponseSchema.parse({
list: result.list,
total: result.
});
}
(handler);
完整示例:
import type { NextApiResponse } from 'next';
import type { ApiRequestProps } from '@fastgpt/service/types/next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import {
GetAppChatLogsBodySchema,
GetAppChatLogsResponseSchema,
type getAppChatLogsResponseType
} from '@fastgpt/global/openapi/core/app/log/api';
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<getAppChatLogsResponseType> {
const { appId, dateStart, dateEnd, sources } = GetAppChatLogsBodySchema.parse(req.body);
await authApp({
req,
authToken: true,
appId,
per: AppReadChatLogPerVal
});
const { list, total } = await getChatLogsFromDB({
appId,
dateStart,
dateEnd,
sources
});
.({
list,
total
});
}
(handler);
步骤 3: 权限验证 (如需要)
使用 authApp 或其他权限验证函数:
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { AppWritePerVal } from '@fastgpt/global/support/permission/app/constant';
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId } = YourAPIBodySchema.parse(req.body);
await authApp({
req,
authToken: true,
appId,
per: AppWritePerVal
});
}
步骤 4: 错误处理
使用统一的错误处理:
import { APIError } from '@fastgpt/service/core/error/controller';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
async function handler(req: ApiRequestProps, res: NextApiResponse) {
try {
const { appId } = YourAPIBodySchema.parse(req.body);
if (!appId) {
return Promise.reject(CommonErrEnum.missingParams);
}
} catch (error) {
return APIError(error)(req, res);
}
}
完整开发示例
场景: 创建用户 API
1. 定义 Schema (packages/global/openapi/core/user/api.ts):
import { z } from 'zod';
export const CreateUserBodySchema = z.object({
name: z.string().min(2).max(50).meta({
example: 'Alice',
description: '用户名 (2-50 字符)'
}),
email: z.string().email().meta({
example: 'alice@example.com',
description: '用户邮箱'
}),
age: z.number().int().positive().optional().meta({
example: 25,
description: '用户年龄'
}),
avatar: z.string().url().optional().meta({
example: 'https://example.com/avatar.jpg',
description: '头像 URL'
})
});
createUserBodyType = z.< >;
= z.({
: z.().({ : , : }),
: z.().({ : , : }),
: z.().({ : , : }),
: z.().({ : , : })
});
createUserResponseType = z.< >;
2. 实现 API (projects/app/src/pages/api/core/user/create.ts):
import type { NextApiResponse } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import type { ApiRequestProps } from '@fastgpt/service/types/next';
import { MongoUser } from '@fastgpt/service/core/user/schema';
import {
CreateUserBodySchema,
CreateUserResponseSchema,
type createUserResponseType
} from '@fastgpt/global/openapi/core/user/api';
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<createUserResponseType> {
const { name, email, age, avatar } = CreateUserBodySchema.parse(req.body);
const existingUser = await MongoUser.findOne({ email });
if (existingUser) {
return Promise.reject('Email already exists');
}
user = .({
name,
email,
age,
avatar,
: ()
});
.({
: user..(),
: user.,
: user.,
: user.
});
}
(handler);
审查检查清单
🔴 必须检查项 (阻塞性)
Schema 文件 (packages/global/openapi/.../api.ts):
API 路由文件 (projects/app/src/pages/api/.../route.ts):
🟡 推荐检查项 (建议性)
🟢 可选检查项 (优化性)
常见问题和解决方案
问题 1: 缺少 API 声明
错误示例:
import { z } from 'zod';
export const GetUserSchema = z.object({
id: z.string()
});
正确做法:
import { z } from 'zod';
export const GetUserSchema = z.object({
id: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '用户 ID'
})
});
问题 2: 类型不匹配
错误示例:
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const data = YourAPIBodySchema.parse(req.body);
return { success: true, data };
}
正确做法:
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<yourAPIResponseType> {
const data = YourAPIBodySchema.parse(req.body);
return YourAPIResponseSchema.parse({
success: true,
data
});
}
问题 3: 缺少 Meta 信息
错误示例:
export const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string()
});
正确做法:
export const UserSchema = z.object({
id: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '用户 ID'
}),
name: z.string().meta({
example: 'Alice',
description: '用户名'
}),
email: z.string().email().meta({
example: 'alice@example.com',
description: '用户邮箱'
})
});
问题 4: 未验证出参
错误示例:
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId } = YourAPIBodySchema.parse(req.body);
const result = await getData(appId);
return result;
}
正确做法:
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId } = YourAPIBodySchema.parse(req.body);
const result = await getData(appId);
return YourAPIResponseSchema.parse(result);
}
问题 5: Schema 复用不当
不好做法:
export const Schema1 = z.object({
id: z.string(),
name: z.string(),
email: z.string()
});
export const Schema2 = z.object({
id: z.string(),
name: z.string(),
email: z.string()
});
正确做法:
export const BaseUserSchema = z.object({
id: z.string().meta({ description: 'ID' }),
name: z.string().meta({ description: '名称' }),
email: z.string().email().meta({ description: '邮箱' })
});
export const Schema1 = z.object({
user: BaseUserSchema
});
export const Schema2 = z.object({
users: z.array(BaseUserSchema)
});
快速参考
API 声明模板
常用标签
- 模块标签:
App, User, Chat, Workflow, Dataset
- 操作类型:
Read, Write, Delete, Update
- 其他:
Admin, Public, Internal
常用 Zod 验证方法
z.string()
.min(2)
.max(50)
.email()
.url()
.uuid()
z.number()
.int()
.positive()
.min(0)
.max(100)
z.boolean()
z.date()
.or(z.string())
z.enum(['active', 'inactive'])
z.nativeEnum(MyEnum)
z.array(z.string())
.()
.()
z.().()
z.().()
z.({
: z.(),
: z.()
})
.({
: z.()
})
z.([z.(), z.()])
z.(, {
: ,
:
})
Meta 字段说明
z.string().meta({
example: 'value',
description: '字段说明'
})
TypeScript 类型导出
export const UserSchema = z.object({
id: z.string(),
name: z.string()
});
export type userType = z.infer<typeof UserSchema>;
export type UserType = z.infer<typeof UserSchema>;
参考资源
项目内示例
- API Schema 示例:
/Volumes/code/fastgpt-pro/FastGPT/packages/global/openapi/core/app/log/api.ts
- API 实现示例:
/Volumes/code/fastgpt-pro/FastGPT/projects/app/src/pages/api/core/app/logs/list.ts
- 分页 Schema:
packages/global/openapi/api.ts
相关文档
- Zod 官方文档: https://zod.dev/
- FastGPT API 规范:
.claude/skills/pr-review/fastgpt-style-guide.md
- PR Review 审查维度:
.claude/skills/pr-review/code-quality-standards.md
Version: 1.0
Last Updated: 2026-01-27
Maintainer: FastGPT Development Team