InsForge API 统一响应格式详解:success/data/meta 契约、错误码体系与分页规范
【免费下载链接】InsForgeThe all-in-one, open-source backend platform for agentic coding. InsForge gives your coding agent database, auth, storage, compute, hosting, and AI gateway to ship full-stack apps end-to-end.项目地址: https://gitcode.com/GitHub_Trending/in/InsForge
本指南以 InsForge 仓库中的 response-examples.md 为核心,系统梳理 InsForge 后端 API 的统一响应格式契约——包括成功响应、错误响应的 JSON 结构、分页元数据、各模块端点示例与错误码语义,并结合
backend/src/utils/response.ts、backend/src/api/middlewares/error.ts、packages/shared-schemas/src/error-codes.schema.ts等源码,解释这套格式在真实请求处理链路中如何落地。读完本文,你将能够按 InsForge 的规范解析任意接口返回、编写统一的错误处理与分页逻辑,并基于共享错误码为 Agent/LLM 客户端设计稳定的交互协议。
为什么需要统一响应格式
Agent 驱动的全栈开发中,编码代理会直接调用后端 API 完成建表、写记录、发邮件、部署函数等操作。如果每个端点返回的 JSON 结构都各不相同,客户端(尤其是大语言模型驱动的 Agent)将难以泛化地解析结果、判断成功与否、恢复错误。为此 InsForge 为所有 API 响应定义了统一契约,核心是success字段与规范化的data/error/meta分层结构。
在仓库中,这套契约由多个模块协同支撑:
- backend/src/utils/response.ts:提供
successResponse、errorResponse、paginatedResponse等响应辅助函数; - backend/src/api/middlewares/error.ts:全局错误中间件,统一拦截并格式化所有异常;
- backend/src/utils/errors.ts:定义
AppError、PostgreSQL 错误映射表POSTGRES_ERROR_HANDLERS与UpstreamError; - packages/shared-schemas/src/error-codes.schema.ts:跨后端、SDK、CLI、MCP 与工具共享的规范化错误码枚举。
成功响应格式(Success Response)
所有成功响应遵循以下结构:
{ "success": true, "data": <response_data>, "meta": { "timestamp": "2024-01-01T00:00:00.000Z", "pagination": { "total": 100, "limit": 10, "offset": 0, "page": 1, "totalPages": 10 } } }字段语义:
| 字段 | 类型 | 说明 |
|---|---|---|
success | boolean | 固定为true,客户端可直接据此判断请求是否成功 |
data | any | 业务数据主体,随端点不同而不同:可能是对象、数组或纯字符串消息 |
meta.timestamp | string(ISO 8601) | 服务端生成响应的 UTC 时间戳,便于日志与调试对齐 |
meta.pagination | object | 可选,仅列表类端点返回,描述分页状态(详见下文"分页元数据") |
值得注意的边界情况:meta.pagination是可选字段,仅出现在列表端点中;单个资源查询、写操作等端点通常只携带timestamp。
错误响应格式(Error Response)
请求失败时,统一返回success: false并携带结构化的错误对象:
{ "success": false, "error": { "code": "ERROR_CODE", "message": "Human readable error message", "details": {} }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }字段语义:
| 字段 | 类型 | 说明 |
|---|---|---|
success | boolean | 固定为false |
error.code | string | 机器可读的错误码(见下文"常见错误码"),客户端应基于code而非message做分支处理 |
error.message | string | 人类可读的错误描述,可直接展示给终端用户或喂给 Agent 参考 |
error.details | object | 可选,补充上下文信息(如校验失败的字段清单、冲突的唯一键等) |
meta.timestamp | string | 同成功响应 |
从源码看,这套错误契约在 backend/src/api/middlewares/error.ts 中被强制统一。errorMiddleware是注册在 backend/src/server.ts 的全局兜底处理器,其处理优先级为:
AppError实例:直接以其code、message、statusCode、nextActions生成响应;JSON解析SyntaxError:映射为INVALID_INPUT(400);pg.DatabaseError:查 backend/src/utils/errors.ts 中的POSTGRES_ERROR_HANDLERS映射表,把 PostgreSQL 错误码翻译为业务错误码与状态码;- body-parser 的
entity.parse.failed:映射为INVALID_INPUT(400); - 其余未知错误:兜底为
INTERNAL_ERROR(500),避免向客户端泄露内部堆栈。
也就是说,无论业务代码抛出何种异常,客户端最终收到的错误结构都是一致的,这为 Agent 编写通用重试与恢复逻辑提供了可靠前提。
分页元数据(Pagination)
列表端点通过meta.pagination返回分页状态,字段含义如下:
| 字段 | 说明 |
|---|---|
total | 符合条件的记录总数 |
limit | 本次请求每页最大条数 |
offset | 本次查询跳过的记录数(从 0 开始) |
page | 当前页码(从 1 开始) |
totalPages | 总页数(由total与limit计算得出) |
示例:请求第 2 页、每页 10 条时,offset=10, limit=10, page=2。
在共享 schema 层,packages/shared-schemas/src/database-api.schema.ts 中定义了管理端记录列表响应的分页结构(offset: int >= 0、limit: int >= 1、total: int >= 0),供类型生成与校验使用。此外 backend/src/utils/response.ts 中的paginatedResponse提供了另一种基于 HTTP 头的分页形式(PostgREST 风格),会设置Content-Range: start-end/total与Preference-Applied: count=exact响应头,并在未返回全部结果时使用206 Partial Content状态码——两种方式分别服务于 JSON 契约型客户端与 PostgREST 兼容型客户端。
各模块端点响应示例
认证端点(Authentication Endpoints)
POST /auth/register
Success Response (201):
{ "success": true, "data": { "user": { "id": "123", "email": "user@example.com" }, "token": "eyJhbGciOiJIUzI1NiIs..." }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }Error Response (400):
{ "success": false, "error": { "code": "ALREADY_EXISTS", "message": "User already exists" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }POST /auth/login
Success Response (200):
{ "success": true, "data": { "user": { "id": "123", "name": "John Doe", "email": "user@example.com" }, "token": "eyJhbGciOiJIUzI1NiIs..." }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }Error Response (401):
{ "success": false, "error": { "code": "INVALID_CREDENTIALS", "message": "Invalid credentials" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }GET /auth/me
Success Response (200):
{ "success": true, "data": { "user": { "id": "123", "email": "user@example.com", "type": "user" } }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }GET /auth/users
Success Response (200):
{ "success": true, "data": [ { "id": "123", "email": "user1@example.com", "created_at": "2024-01-01T00:00:00.000Z", "updated_at": "2024-01-01T00:00:00.000Z" }, { "id": "124", "email": "user2@example.com", "created_at": "2024-01-01T00:00:00.000Z", "updated_at": "2024-01-01T00:00:00.000Z" } ], "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }真实路由实现中,认证端点位于 backend/src/api/routes/auth/index.routes.ts,全部通过successResponse(res, result)输出响应;例如POST /api/auth/logout会返回{ success: true, message: 'Logged out successfully' },POST /api/auth/email/send-otp以202 Accepted返回{ success: true, message: ... }。同时,web 客户端走 httpOnly Cookie + CSRF Token 的会话流程,非 web 客户端(mobile/desktop/server)则在响应体中直接拿到refreshToken,success: true的存在让两类客户端都能用同一套判断逻辑。
数据表端点(Tables Endpoints)
GET /database/tables
Success Response (200):
{ "success": true, "data": ["posts", "comments"], "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }POST /database/tables
Success Response (201):
{ "success": true, "data": { "message": "Table created successfully", "table_name": "posts" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }GET /database/records/:table
Success Response with Pagination (200):
{ "success": true, "data": [ { "id": 1, "title": "First Post", "content": "Hello World" }, { "id": 2, "title": "Second Post", "content": "Another post" } ], "meta": { "pagination": { "total": 50, "limit": 10, "offset": 0, "page": 1, "totalPages": 5 }, "timestamp": "2024-01-01T00:00:00.000Z" } }GET /database/records/:table?id=eq.:id
Success Response (200):
{ "success": true, "data": { "id": 1, "title": "First Post", "content": "Hello World", "created_at": "2024-01-01T00:00:00.000Z" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }Error Response (404):
{ "success": false, "error": { "code": "NOT_FOUND", "message": "Record not found" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }POST /database/records/:table
Success Response (201):
{ "success": true, "data": { "message": "Records inserted successfully", "inserted": 3, "ids": [1, 2, 3] }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }PATCH /database/records/:table?id=eq.:id
Success Response (200):
{ "success": true, "data": { "message": "Record updated successfully", "affected": 1 }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }DELETE /database/records/:table?id=eq.:id
Success Response (200):
{ "success": true, "data": { "message": "Record deleted successfully", "affected": 1 }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }GET /database/tables/:table/schema
Success Response (200):
{ "success": true, "data": { "table_name": "posts", "columns": [ { "name": "id", "type": "INTEGER", "nullable": false, "primary_key": true, "default_value": null }, { "name": "title", "type": "TEXT", "nullable": false, "primary_key": false, "default_value": null } ] }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }PATCH /database/tables/:table
Success Response (200):
{ "success": true, "data": { "message": "Table schema updated successfully", "table_name": "posts", "operations": [ "Added column: tags", "Renamed column: content → body", "Dropped columns: temp_field" ] }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }注意operations数组逐条列出了本次 schema 变更的具体动作(新增列、重命名列、删除列),Agent 客户端可以据此向用户汇报变更明细。
DELETE /database/tables/:table
Success Response (200):
{ "success": true, "data": { "message": "Table deleted successfully", "table_name": "posts" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }元数据端点(Metadata Endpoints)
GET /metadata
Success Response (200):
{ "success": true, "data": { "app_name": "My InsForge App", "app_description": "Backend as a Service", "created_at": "2024-01-01T00:00:00.000Z" }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }GET /metadata/api-key
Success Response (200):
{ "success": true, "data": { "api_key": "ik_1234567890abcdef..." }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }MCP 端点(MCP Endpoints)
GET /mcp/metadata
Success Response (200):
{ "success": true, "data": { "app_name": "My InsForge App", "app_description": "Backend as a Service", "mcp_tools": { "database": { "create_table": true, "modify_table": true, "delete_table": true, "query_records": true, "insert_records": true, "update_records": true, "delete_records": true } } }, "meta": { "timestamp": "2024-01-01T00:00:00.000Z" } }mcp_tools.database以布尔值声明了当前项目对各类数据库工具的能力开关,MCP 客户端(如 Cursor、Claude Code 等编码代理)可据此决定暴露哪些工具,避免调用未开启的能力。
系统端点(System Endpoints)
GET /health
Success Response (200):
{ "success": true, "data": { "status": "ok", "service": "Insforge Backend", "timestamp": "2024-01-01T00:00:00.000Z" } }常见错误码一览
文档给出了通用错误码速查表:
| 错误码 | 含义 |
|---|---|
MISSING_AUTH | 未提供任何认证信息 |
INVALID_AUTH | 认证 Token 或 API Key 无效 |
INVALID_CREDENTIALS | 用户名/密码错误 |
TOKEN_EXPIRED | JWT Token 已过期 |
FORBIDDEN | 访问被拒绝 |
INSUFFICIENT_PERMISSIONS | 缺少所需权限 |
VALIDATION_ERROR | 输入校验失败 |
INVALID_INPUT | 输入格式无效 |
MISSING_FIELD | 缺少必填字段 |
NOT_FOUND | 资源不存在 |
ALREADY_EXISTS | 资源已存在 |
DATABASE_ERROR | 数据库操作失败 |
CONSTRAINT_VIOLATION | 违反数据库约束 |
INTERNAL_ERROR | 服务端内部错误 |
SERVICE_UNAVAILABLE | 服务暂时不可用 |
这些通用码只是错误码体系的一部分。从源码看,InsForge 将错误码收敛为一份跨端共享的枚举 packages/shared-schemas/src/error-codes.schema.ts,通过 Zod 的z.enum定义并导出ERROR_CODES,后端、SDK、CLI、MCP 与工具统一引用同一常量,保证字符串值稳定。按模块划分为:
- 认证:
AUTH_INVALID_EMAIL、AUTH_WEAK_PASSWORD、AUTH_INVALID_CREDENTIALS、AUTH_INVALID_API_KEY、AUTH_EMAIL_EXISTS、AUTH_USER_NOT_FOUND、AUTH_TOKEN_EXPIRED、AUTH_UNAUTHORIZED、AUTH_NEED_VERIFICATION、AUTH_SIGNUP_DISABLED等; - 数据库:
DATABASE_INVALID_PARAMETER、DATABASE_VALIDATION_ERROR、DATABASE_CONSTRAINT_VIOLATION、DATABASE_NOT_FOUND、DATABASE_DUPLICATE、DATABASE_PERMISSION_DENIED、DATABASE_INTERNAL_ERROR等; - 存储:
STORAGE_ALREADY_EXISTS、STORAGE_INVALID_FILE_TYPE、STORAGE_INSUFFICIENT_QUOTA、STORAGE_NOT_FOUND、STORAGE_PERMISSION_DENIED、S3_ACCESS_KEY_LIMIT_EXCEEDED等; - 实时:
REALTIME_CHANNEL_NOT_FOUND、REALTIME_UNAUTHORIZED、REALTIME_INVALID_EVENT等; - AI:
AI_INVALID_API_KEY、AI_INVALID_MODEL、AI_UPSTREAM_UNAVAILABLE; - 计算:
COMPUTE_CLOUD_UNAVAILABLE、COMPUTE_QUOTA_EXCEEDED、COMPUTE_SERVICE_DEPLOY_FAILED等; - 部署/函数/定时任务:
DEPLOYMENT_NOT_FOUND、FUNCTION_SLUG_RESERVED、SCHEDULE_INVALID_CRON等; - 支付:
PAYMENT_METHOD_DECLINED、PAYMENT_CHECKOUT_ALREADY_EXISTS等; - 通用:
MISSING_FIELD、ALREADY_EXISTS、INVALID_INPUT、NOT_FOUND、INTERNAL_ERROR、TOO_MANY_REQUESTS、RATE_LIMITED、UPSTREAM_FAILURE等。
源码中的错误映射与兜底策略
统一格式不仅体现在文档层面,更落实在错误处理链路中:
1. AppError 业务异常:业务代码通过throw new AppError(message, statusCode, code, nextActions?)主动抛错(见 backend/src/utils/errors.ts),errorMiddleware直接消费该结构输出标准错误响应。
2. PostgreSQL 原生错误翻译:POSTGRES_ERROR_HANDLERS将常见的 pg 错误码映射为业务错误码与对应 HTTP 状态码(见 backend/src/utils/errors.ts):
| PostgreSQL 错误码 | 业务错误码 | HTTP 状态码 |
|---|---|---|
23505(唯一冲突) | DATABASE_DUPLICATE | 409 |
23503(外键约束) | DATABASE_CONSTRAINT_VIOLATION | 400 |
23502(非空约束) | MISSING_FIELD | 400 |
42P01(表不存在) | DATABASE_VALIDATION_ERROR | 400 |
42701(重复列) | DATABASE_VALIDATION_ERROR | 400 |
42703(列不存在) | DATABASE_VALIDATION_ERROR | 400 |
42830(唯一约束) | DATABASE_VALIDATION_ERROR | 400 |
42804(类型不匹配) | DATABASE_VALIDATION_ERROR | 400 |
42501(RLS 权限) | FORBIDDEN | 403 |
映射结果还附带nextActions修复建议(如CHECK_UNIQUE_FIELD、FILL_REQUIRED_FIELD、CHECK_RLS_POLICY),这些建议定义在 backend/src/utils/next-actions.ts,能直接引导 Agent 客户端进行下一步修复操作。
3. 上游服务错误兜底:UpstreamError从上游响应中提取错误信息与状态码,默认回落为UPSTREAM_FAILURE/ 502(见 backend/src/utils/errors.ts),保证调用方(AI 网关、部署器、Webhook 等)出错时仍输出结构化错误而非裸异常。
客户端接入实践建议
基于这套契约,无论用 curl、TypeScript SDK 还是 Agent 工具调用,都可以遵循以下模式:
1. 统一判断成功与否
不要依赖 HTTP 状态码或对data的猜测,优先检查success字段:
{ "success": true, "data": { ... } }2. 按错误码分支处理
错误处理应以error.code为 switch 依据,而非匹配message文本。例如:
INVALID_CREDENTIALS/TOKEN_EXPIRED→ 触发重新登录或刷新 Token;MISSING_FIELD/VALIDATION_ERROR→ 根据details补齐参数后重试;RATE_LIMITED/TOO_MANY_REQUESTS→ 退避重试;NOT_FOUND/ALREADY_EXISTS→ 调整目标资源后继续;DATABASE_DUPLICATE→ 依据nextActions中提示的字段名去重。
3. 翻页遍历列表
列表端点根据meta.pagination循环拉取全部数据:
第 1 页:offset=0, limit=10 → totalPages=5 第 2 页:offset=10, limit=10 ... 第 5 页:offset=40, limit=10 → 结束4. 保留时间戳用于调试
meta.timestamp让客户端可以把本地请求时间与服务端响应时间对齐,便于排查时钟偏差与网络延迟问题。
小结
InsForge 通过success/data/error/meta的统一响应契约,把"成功判定、错误分类、分页导航"三件事标准化:前端与 Agent 只需实现一套解析与重试逻辑即可覆盖认证、数据库、存储、函数、支付等全部模块;后端通过 error.ts 全局中间件、errors.ts 的错误映射与 error-codes.schema.ts 的共享枚举保证契约不被破坏。在接入 InsForge 时,建议以本文的格式规范为准编写类型定义与 SDK 封装,从而获得跨端点一致的开发体验。
【免费下载链接】InsForgeThe all-in-one, open-source backend platform for agentic coding. InsForge gives your coding agent database, auth, storage, compute, hosting, and AI gateway to ship full-stack apps end-to-end.项目地址: https://gitcode.com/GitHub_Trending/in/InsForge
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考