# API 接口文档 > AI 项目导航站对外提供的 REST API 接口文档 ## 目录 - [1. 概述](#1-概述) - [2. 认证方式](#2-认证方式) - [3. 接口列表](#3-接口列表) - [3.1 创建/更新项目 (Webhook)](#31-创建更新项目-webhook) - [3.2 获取项目详情](#32-获取项目详情) - [3.3 删除项目](#33-删除项目) - [3.4 项目发现系统 API](#34-项目发现系统-api) - [3.5 去重检查 API](#35-去重检查-api) - [4. 数据模型](#4-数据模型) - [5. 错误码](#5-错误码) --- ## 1. 概述 ### 1.1 Base URL ``` 生产环境: https://your-domain.com 开发环境: http://localhost:3000 ``` ### 1.2 响应格式 所有接口返回 JSON 格式数据: ```typescript // 成功响应 { "success": true, "data": { ... }, "message": "操作成功" } // 错误响应 { "success": false, "error": "错误类型", "details": ["详细错误信息1", "详细错误信息2"] } ``` ### 1.3 通用请求头 ``` Content-Type: application/json x-api-key: your-api-key-here # 需要认证的接口 ``` --- ## 2. 认证方式 ### API Key 认证 所有 API 接口均使用 API Key 进行认证。API Key 通过请求头 `x-api-key` 传递。 ```bash # 设置环境变量 WEBHOOK_API_KEY=your-secret-api-key # 请求示例 curl -X POST https://your-domain.com/api/webhook/projects \ -H "Content-Type: application/json" \ -H "x-api-key: your-secret-api-key" \ -d '...' ``` **注意事项**: - API Key 需要在服务端环境变量中配置 `WEBHOOK_API_KEY` - 请妥善保管 API Key,不要在客户端代码中暴露 - 建议定期轮换 API Key --- ## 3. 接口列表 ### 3.1 创建/更新项目 (Webhook) 批量创建或更新项目数据。支持多级去重策略自动识别已存在的项目。 #### 3.1.1 接口信息 ``` POST /api/webhook/projects ``` #### 3.1.2 请求参数 **Headers**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | x-api-key | string | 是 | API 密钥 | | Content-Type | string | 是 | 必须为 `application/json` | **Body**: ```typescript { apiKey: string; // API 密钥(与 header x-api-key 二选一) projects: ProjectInput[]; // 项目数组(1-100个) } ``` **ProjectInput 类型**: ```typescript { // 基础信息(必填) name: string; // 中文名称 (1-200 字符) nameEn?: string; // 英文名称(可选,1-200 字符) description: string; // 中文描述 (10-500 字符) descriptionEn?: string; // 英文描述(可选,10-500 字符) // 内容(可选) content?: string; // 中文内容(Markdown 格式,最大 10000 字符) contentEn?: string; // 英文内容(Markdown 格式,最大 10000 字符) // 状态(可选) status?: "ACTIVE" | "ARCHIVED"; // 默认: "ACTIVE" source?: string; // 数据来源标识 // 关联(必填) tags: Array<{ // 标签数组(1-10个) name: string; // 标签名 nameEn?: string; // 英文标签名(可选) }>; links: Array<{ // 外部链接数组(1-10个) type: "WEBSITE" | "GITHUB" | "HUGGINGFACE" | "PAPER"; url: string; // 链接 URL title?: string; // 链接标题(可选) }>; } ``` #### 3.1.3 多级去重策略 Webhook 会按以下优先级识别已存在的项目: 1. **GitHub URL 精确匹配**(最准确) 2. **Website URL 精确匹配** 3. **slug 匹配**(兜底) 如果找到已存在的项目,将执行更新操作: - 更新所有项目字段 - 替换所有标签(删除旧的,创建新的) - 替换所有链接(删除旧的,创建新的) #### 3.1.4 请求示例 ```bash curl -X POST https://your-domain.com/api/webhook/projects \ -H "Content-Type: application/json" \ -H "x-api-key: your-api-key" \ -d '{ "apiKey": "your-api-key", "projects": [ { "name": "LangChain", "nameEn": "LangChain", "description": "开发由语言模型驱动的应用程序框架", "descriptionEn": "Developing applications powered by language models", "content": "# LangChain\n\nLangChain 是一个...", "contentEn": "# LangChain\n\nLangChain is a...", "status": "ACTIVE", "source": "GITHUB", "tags": [ { "name": "LLM", "nameEn": "Large Language Model" }, { "name": "Python", "nameEn": "Python" }, { "name": "开发框架", "nameEn": "Development Framework" } ], "links": [ { "type": "GITHUB", "url": "https://github.com/langchain-ai/langchain", "title": "GitHub 仓库" }, { "type": "WEBSITE", "url": "https://langchain.com", "title": "官方网站" } ] } ] }' ``` #### 3.1.5 响应示例 **成功响应** (200 OK): ```json { "success": true, "processed": 1, "created": 0, "updated": 1, "failed": 0, "errors": [] } ``` **错误响应** (400 Bad Request): ```json { "success": false, "error": "Validation error", "details": [ "tags: Field must contain at least 1 element", "links: Field must contain at most 10 elements" ] } ``` **认证失败** (401 Unauthorized): ```json { "success": false, "error": "Unauthorized", "details": ["Invalid or missing API Key"] } ``` --- ### 3.2 获取项目详情 根据项目的 slug 获取项目详细信息。 #### 3.2.1 接口信息 ``` GET /api/projects/:slug ``` #### 3.2.2 路径参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | slug | string | 是 | 项目的唯一标识符 | #### 3.2.3 请求示例 ```bash curl -X GET https://your-domain.com/api/projects/langchain \ -H "Content-Type: application/json" ``` #### 3.2.4 响应示例 **成功响应** (200 OK): ```json { "success": true, "data": { "id": "clx1234567890", "name": "LangChain", "nameEn": "LangChain", "slug": "langchain", "description": "开发由语言模型驱动的应用程序框架", "descriptionEn": "Developing applications powered by language models", "content": "# LangChain\n\nLangChain 是一个...", "contentEn": "# LangChain\n\nLangChain is a...", "status": "ACTIVE", "source": "GITHUB", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-15T00:00:00.000Z", "links": [ { "id": "link123", "type": "GITHUB", "url": "https://github.com/langchain-ai/langchain", "title": "GitHub 仓库" } ], "tags": [ { "id": "tag123", "name": "LLM", "nameEn": "Large Language Model", "slug": "large-language-model" } ] } } ``` **项目不存在** (404 Not Found): ```json { "success": false, "error": "Not Found", "details": ["Project with slug \"nonexistent\" not found"] } ``` --- ### 3.3 删除项目 根据项目的 slug 删除项目及其所有关联数据。 #### 3.3.1 接口信息 ``` DELETE /api/projects/:slug ``` #### 3.3.2 路径参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | slug | string | 是 | 项目的唯一标识符 | #### 3.3.3 请求头 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | x-api-key | string | 是 | API 密钥 | | Content-Type | string | 是 | 必须为 `application/json` | #### 3.3.4 级联删除说明 由于数据库配置了 `onDelete: Cascade`,删除项目时会自动删除: - ✅ 该项目的所有外部链接(`ExternalLink`) - ✅ 该项目的所有标签关联(`ProjectTag`) - ❌ Tag 本身不会被删除(只删除项目与标签的关联关系) #### 3.3.5 请求示例 ```bash curl -X DELETE https://your-domain.com/api/projects/langchain \ -H "Content-Type: application/json" \ -H "x-api-key: your-api-key" ``` #### 3.3.6 响应示例 **成功响应** (200 OK): ```json { "success": true, "message": "Project deleted successfully", "data": { "project": { "id": "clx1234567890", "name": "LangChain", "nameEn": "LangChain", "slug": "langchain" }, "deleted": { "linksCount": 2, "tagsCount": 3 } } } ``` **项目不存在** (404 Not Found): ```json { "success": false, "error": "Not Found", "details": ["Project with slug \"nonexistent\" not found"] } ``` **认证失败** (401 Unauthorized): ```json { "success": false, "error": "Unauthorized", "details": ["Invalid or missing API Key"] } ``` --- ### 3.4 项目发现系统 API 项目发现系统用于自动化探索和收录 AI 项目,支持任务创建、状态追踪和项目提交。 #### 3.4.1 创建探索任务 批量创建新的项目探索任务。 ``` POST /api/discovery/tasks ``` **请求体**: ```typescript { apiKey: string; // API 密钥 tasks: Array<{ sourceUrl: string; // 探索目标 URL (GitHub 仓库链接等) sourceType?: string; // 来源类型,默认 "manual" }>; // 1-50 个任务 } ``` **响应示例** (200 OK): ```json { "success": true, "created": 5, "skipped": 2, "total": 7 } ``` **去重逻辑**: - 如果 `sourceUrl` 已存在任务,自动跳过并计入 `skipped` --- #### 3.4.2 获取任务列表 获取待处理或指定状态的探索任务列表。 ``` GET /api/discovery/tasks?status=PENDING&limit=10&offset=0 ``` **查询参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | status | string | 否 | 筛选状态: PENDING/IN_PROGRESS/COMPLETED/FAILED | | limit | number | 否 | 每页数量,默认 10,最大 100 | | offset | number | 否 | 偏移量,默认 0 | **请求头**: ``` x-api-key: your-api-key ``` **响应示例** (200 OK): ```json { "success": true, "tasks": [ { "id": "clx1234567890", "sourceUrl": "https://github.com/user/repo", "sourceType": "manual", "status": "PENDING", "createdAt": "2024-01-15T00:00:00.000Z", "startedAt": null, "completedAt": null, "projectId": null, "explorationData": null, "explorationSummary": null, "errorMessage": null, "retryCount": 0 } ], "total": 25, "hasMore": true } ``` --- #### 3.4.3 获取任务详情 获取单个探索任务的详细信息。 ``` GET /api/discovery/tasks/:id ``` **无需认证** (只读端点) **响应示例** (200 OK): ```json { "success": true, "task": { "id": "clx1234567890", "sourceUrl": "https://github.com/user/repo", "sourceType": "manual", "status": "COMPLETED", "createdAt": "2024-01-15T00:00:00.000Z", "startedAt": "2024-01-15T00:01:00.000Z", "completedAt": "2024-01-15T00:05:00.000Z", "projectId": "clx0987654321", "explorationData": { ... }, "explorationSummary": "LangChain 是一个 LLM 应用开发框架...", "errorMessage": null, "retryCount": 0 } } ``` --- #### 3.4.4 更新任务状态 更新探索任务的状态和相关信息。 ``` PATCH /api/discovery/tasks/:id ``` **请求体**: ```typescript { apiKey: string; status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED'; explorationData?: Record; // 探索结果数据 (JSON) explorationSummary?: string; // 探索摘要,最大 1000 字符 errorMessage?: string; // 错误信息,最大 2000 字符 } ``` **状态转换规则**: | 当前状态 | 允许转换到 | |----------|------------| | PENDING | IN_PROGRESS | | IN_PROGRESS | COMPLETED, FAILED | | COMPLETED | (终态,不可转换) | | FAILED | PENDING (允许重试) | **响应示例** (200 OK): ```json { "success": true, "task": { "id": "clx1234567890", "status": "IN_PROGRESS", "startedAt": "2024-01-15T00:01:00.000Z", ... } } ``` --- #### 3.4.5 完成任务并提交项目 完成探索并提交项目数据(自动创建或更新项目)。 ``` POST /api/discovery/tasks/:id/complete ``` **请求体**: ```typescript { apiKey: string; explorationData: ProjectInput; // 符合 ProjectInputSchema 的项目数据 } ``` **功能说明**: - 验证 `explorationData` 格式 - 多级去重策略识别已存在项目(GitHub URL → Website URL → slug) - 使用事务确保任务状态更新和项目创建/更新的原子性 - 成功时任务状态更新为 COMPLETED,关联 projectId - 失败时任务状态更新为 FAILED,记录错误信息 **响应示例** (200 OK): ```json { "success": true, "taskId": "clx1234567890", "projectId": "clx0987654321", "action": "created", "duration": 1234 } ``` **错误响应** (400 Bad Request): ```json { "success": false, "error": "Invalid exploration data format", "details": [ "tags: Field must contain at least 1 element", "links: Field must contain at least 1 element" ] } ``` --- #### 3.4.6 检查任务去重 在创建任务前检查 URL 是否应该创建新任务。 ``` POST /api/discovery/check-duplicates ``` **请求体**: ```typescript { apiKey: string; urls: string[]; // 1-100 个 URL sourceType?: string; // 可选来源标识 } ``` **去重优先级**: 1. PENDING/IN_PROGRESS 任务 → 不创建(任务处理中) 2. COMPLETED/FAILED 任务 → 不创建(已探索过) 3. 已存在的项目(通过 ExternalLink)→ 不创建(已收录) 4. 无任何记录 → 允许创建 **响应示例** (200 OK): ```json { "success": true, "results": [ { "url": "https://github.com/langchain-ai/langchain", "shouldCreate": false, "reason": "Task already completed", "existingTask": { "id": "clx123", "status": "COMPLETED", "sourceUrl": "https://github.com/langchain-ai/langchain", "createdAt": "2024-01-15T00:00:00.000Z", "projectId": "clx456" }, "existingProject": { "id": "clx456", "name": "LangChain", "slug": "langchain" } } ], "stats": { "total": 10, "shouldCreate": 5, "duplicate": 5 } } ``` --- ### 3.5 去重检查 API 检查项目是否已存在(用于提交前的预检查)。 #### 3.5.1 检查项目去重 根据 URL 或 slug 检查项目是否已存在。 ``` POST /api/webhook/check-duplicates ``` **请求体**: ```typescript { apiKey: string; projects: Array<{ githubUrl?: string; huggingfaceUrl?: string; websiteUrl?: string; slug?: string; }>; } ``` **匹配优先级**: 1. GitHub URL 精确匹配 2. Hugging Face URL 精确匹配 3. Website URL 精确匹配 4. slug 匹配(兜底) **响应示例** (200 OK): ```json { "success": true, "results": [ { "githubUrl": "https://github.com/langchain-ai/langchain", "exists": true, "matchType": "GITHUB_URL", "projectId": "clx456", "projectName": "LangChain" }, { "websiteUrl": "https://newproject.com", "exists": false, "matchType": "NONE" } ], "stats": { "total": 2, "exists": 1, "new": 1, "breakdown": { "githubUrl": 1, "huggingfaceUrl": 0, "websiteUrl": 0, "slug": 0 } } } ``` --- ## 4. 数据模型 ### 4.1 Project 状态枚举 ```typescript enum ProjectStatus { ACTIVE = "ACTIVE", // 活跃项目 ARCHIVED = "ARCHIVED" // 已归档项目 } ``` ### 4.2 链接类型枚举 ```typescript enum LinkType { WEBSITE = "WEBSITE", // 官方网站 GITHUB = "GITHUB", // GitHub 仓库 HUGGINGFACE = "HUGGINGFACE", // Hugging Face 模型/数据集 PAPER = "PAPER" // 论文链接 } ``` ### 4.3 完整项目模型 ```typescript interface Project { id: string; // 项目唯一 ID(cuid 格式) name: string; // 中文名称 (1-200 字符) nameEn: string | null; // 英文名称 slug: string; // URL 友好标识符(唯一) description: string; // 中文描述 (10-500 字符) descriptionEn: string | null;// 英文描述 content: string | null; // 中文内容(Markdown,最大 10000 字符) contentEn: string | null; // 英文内容(Markdown,最大 10000 字符) status: ProjectStatus; // 项目状态 source: string | null; // 数据来源 createdAt: Date; // 创建时间 updatedAt: Date; // 更新时间 // 关联数据 tags: Tag[]; // 标签数组 links: ExternalLink[]; // 外部链接数组 } ``` ### 4.4 Tag 模型 ```typescript interface Tag { id: string; // 标签唯一 ID name: string; // 中文名称(唯一) nameEn: string | null; // 英文名称 slug: string; // URL 友好标识符(唯一) createdAt: Date; // 创建时间 } ``` ### 4.5 ExternalLink 模型 ```typescript interface ExternalLink { id: string; // 链接唯一 ID type: LinkType; // 链接类型 url: string; // 链接 URL title: string | null; // 链接标题 projectId: string; // 所属项目 ID } ``` ### 4.6 ProjectDiscoveryTask 模型 ```typescript interface ProjectDiscoveryTask { id: string; // 任务唯一 ID (cuid 格式) sourceUrl: string; // 探索目标 URL sourceType: string; // 来源类型 (如 "manual", "github-trending") status: TaskStatus; // 任务状态 createdAt: Date; // 创建时间 startedAt: Date | null; // 开始处理时间 completedAt: Date | null; // 完成时间 projectId: string | null; // 关联的项目 ID (完成后) explorationData: JsonValue | null; // 探索结果数据 (JSON) explorationSummary: string | null; // 探索摘要 errorMessage: string | null; // 错误信息 retryCount: number; // 重试次数 lastRetryAt: Date | null; // 最后重试时间 } ``` ### 4.7 TaskStatus 状态枚举 ```typescript enum TaskStatus { PENDING = 'PENDING', // 待处理 IN_PROGRESS = 'IN_PROGRESS', // 处理中 COMPLETED = 'COMPLETED', // 已完成 FAILED = 'FAILED' // 失败 } ``` --- ## 5. 错误码 ### 5.1 HTTP 状态码 | 状态码 | 说明 | 示例场景 | |--------|------|----------| | 200 OK | 请求成功 | 成功获取/创建/更新/删除数据 | | 400 Bad Request | 请求参数错误 | 必填字段缺失、字段格式错误 | | 401 Unauthorized | 认证失败 | API Key 无效或缺失 | | 404 Not Found | 资源不存在 | 请求的项目 slug 不存在 | | 500 Internal Server Error | 服务器内部错误 | 数据库连接失败、程序异常 | ### 5.2 业务错误类型 | 错误类型 | 说明 | 处理建议 | |----------|------|----------| | Validation error | 数据验证失败 | 检查请求体字段是否符合要求 | | Unauthorized | API Key 无效 | 检查 API Key 是否正确 | | Not Found | 资源不存在 | 确认 slug 是否正确 | | Internal server error | 服务器错误 | 联系技术支持或稍后重试 | ### 5.3 验证规则 #### 项目数据验证 ```typescript // 必填字段 - name: 非空字符串,长度 1-200 - description: 非空字符串,长度 10-500 - tags: 数组,长度 1-10,每个 tag.name 非空 - links: 数组,长度 1-10,每个 link.url 和 link.type 非空 // 可选字段 - nameEn: 字符串,长度 1-200 - descriptionEn: 字符串,长度 10-500 - content/contentEn: 文本类型,支持 Markdown,最大 10000 字符 - status: 枚举值 "ACTIVE" 或 "ARCHIVED",默认 "ACTIVE" - source: 字符串,标识数据来源 // URL 格式 - links[*].url: 必须是有效的 HTTP/HTTPS URL - links[*].type: 必须是 LinkType 枚举值之一 ``` #### Webhook 批量操作限制 ```typescript // 批量操作 - projects: 数组,长度 1-100 - apiKey: 必须与环境变量 WEBHOOK_API_KEY 匹配 ``` --- ## 6. 使用示例 ### 6.1 完整的工作流示例 ```javascript // 1. 创建/更新项目 const createResponse = await fetch('https://your-domain.com/api/webhook/projects', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify({ apiKey: 'your-api-key', projects: [{ name: 'My AI Project', nameEn: 'My AI Project', description: '一个创新的 AI 项目', descriptionEn: 'An innovative AI project', status: 'ACTIVE', source: 'MANUAL', tags: [ { name: 'AI', nameEn: 'Artificial Intelligence' }, { name: '机器学习', nameEn: 'Machine Learning' } ], links: [ { type: 'GITHUB', url: 'https://github.com/user/project', title: 'GitHub' }, { type: 'WEBSITE', url: 'https://project.com', title: 'Website' } ] }] }) }); const createResult = await createResponse.json(); console.log('创建结果:', createResult); // { success: true, processed: 1, created: 1, updated: 0, failed: 0, errors: [] } // 2. 获取项目详情 const slug = 'my-ai-project'; // 根据 nameEn 自动生成 const getResponse = await fetch(`https://your-domain.com/api/projects/${slug}`); const getResult = await getResponse.json(); console.log('项目详情:', getResult.data); // 3. 删除项目 const deleteResponse = await fetch(`https://your-domain.com/api/projects/${slug}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' } }); const deleteResult = await deleteResponse.json(); console.log('删除结果:', deleteResult); ``` ### 6.2 批量创建项目示例 ```javascript const projects = [ { name: '项目 A', nameEn: 'Project A', description: '项目 A 的描述', descriptionEn: 'Description of Project A', tags: [{ name: '分类1' }], links: [{ type: 'GITHUB', url: 'https://github.com/user/a' }] }, { name: '项目 B', nameEn: 'Project B', description: '项目 B 的描述', descriptionEn: 'Description of Project B', tags: [{ name: '分类2' }], links: [{ type: 'GITHUB', url: 'https://github.com/user/b' }] } ]; const response = await fetch('https://your-domain.com/api/webhook/projects', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify({ apiKey: 'your-api-key', projects: projects }) }); const result = await response.json(); console.log('批量创建结果:', result); // { success: true, processed: 2, created: 2, updated: 0, failed: 0, errors: [] } ``` --- ## 7. 注意事项 ### 7.1 Slug 生成规则 项目 slug 根据以下规则自动生成: 1. 优先使用 `nameEn`(英文) 2. 如果 `nameEn` 不存在,使用 `name`(中文) 3. 转换为小写 4. 空格替换为连字符 `-` 5. 移除特殊字符 示例: - `nameEn: "LangChain"` → `slug: "langchain"` - `name: "大语言模型"` → `slug: "大语言模型"` (会进行拼音转换) ### 7.2 标签去重 - 标签的 `name` 字段在数据库中是唯一的 - 如果创建已存在的标签,会自动复用现有标签 - 标签的 `slug` 也是唯一的,会根据 `nameEn` 或 `name` 自动生成 ### 7.3 链接去重 - 同一个项目不能有重复的 URL - 通过 `projectId` + `url` 的组合保证唯一性 ### 7.4 更新策略 - Webhook 使用 **替换策略** 更新标签和链接 - 不是增量更新,而是完全替换 - 更新时会删除旧的标签/链接关联,创建新的 --- ## 8. 附录 ### 8.1 环境变量配置 ```bash # .env WEBHOOK_API_KEY=your-secret-api-key-here DATABASE_URL=postgresql://user:password@host:5432/dbname?sslmode=require ``` ### 8.2 相关文档 - [数据库 Schema](../prisma/schema.prisma) - [数据验证规则](../src/lib/validations.ts) - [数据新增流程设计](./data-ingestion-flow.md) - [项目发现系统](../.claude/commands/discover-projects.md) - [Discovery Service](../src/app/api/discovery/lib/discovery-service.ts) --- **文档版本**: v2.0.0 **最后更新**: 2025-01-20 **维护者**: AI 项目导航站团队