import { jsonOk } from "@/lib/server/api"; import { requestOrigin } from "@/lib/server/runtime"; export const runtime = "nodejs"; export async function GET(request: Request) { return jsonOk({ openapi: "3.1.0", info: { title: "智念AIGC平台 Public API", version: "1.0.0", description: "Public server-to-server API for uploading assets, creating image/video generation jobs, polling job status, downloading outputs, and receiving webhooks." }, servers: [ { url: requestOrigin(request), description: "Current deployment" } ], security: [{ bearerApiKey: [] }, { headerApiKey: [] }], components: { securitySchemes: { bearerApiKey: { type: "http", scheme: "bearer" }, headerApiKey: { type: "apiKey", in: "header", name: "X-Zhinian-Api-Key" } }, schemas: { ErrorResponse: { type: "object", required: ["error"], properties: { error: { type: "string" } } }, Asset: { type: "object", required: ["id", "kind", "name", "url", "source", "createdAt"], properties: { id: { type: "string", example: "asset_mpqe9g85_12635f8cd8" }, ownerId: { type: "string" }, kind: { type: "string", enum: ["image", "video", "mask", "reference", "other"] }, name: { type: "string", example: "result.png" }, url: { type: "string", format: "uri" }, storagePath: { type: "string" }, source: { type: "string", enum: ["upload", "generated", "edited", "upscaled", "external", "seed"] }, tags: { type: "array", items: { type: "string" } }, metadata: { type: "object", additionalProperties: true }, createdAt: { type: "string", format: "date-time" }, updatedAt: { type: "string", format: "date-time" } } }, GenerationJob: { type: "object", required: ["id", "capability", "provider", "status", "createdAt", "updatedAt"], properties: { id: { type: "string", example: "job_mpqe3wtt_12ed738079" }, externalClientId: { type: "string" }, capability: { $ref: "#/components/schemas/GenerationCapability" }, provider: { type: "string", enum: ["volcengine-visual", "evolink", "seedance", "mock"] }, reqKey: { type: "string" }, status: { $ref: "#/components/schemas/GenerationStatus" }, prompt: { type: "string" }, inputAssetIds: { type: "array", items: { type: "string" } }, inputUrls: { type: "array", items: { type: "string", format: "uri" } }, outputAssetIds: { type: "array", items: { type: "string" } }, providerTaskId: { type: "string" }, error: { type: "object", properties: { code: { oneOf: [{ type: "string" }, { type: "number" }] }, message: { type: "string" }, retryable: { type: "boolean" } } }, idempotencyKey: { type: "string" }, priority: { type: "integer" }, attempts: { type: "integer" }, scheduledAt: { type: "string", format: "date-time" }, completedAt: { type: "string", format: "date-time" }, webhookUrl: { type: "string", format: "uri" }, webhookAttempts: { type: "integer" }, webhookLastStatus: { type: "object", additionalProperties: true }, createdAt: { type: "string", format: "date-time" }, updatedAt: { type: "string", format: "date-time" } } }, GenerationCapability: { type: "string", enum: ["image.generate", "image.inpaint", "image.upscale", "video.generate"] }, GenerationStatus: { type: "string", enum: ["queued", "running", "succeeded", "failed", "expired", "cancelled"] }, PromptMaterial: { type: "object", properties: { id: { type: "string" }, url: { type: "string", format: "uri" }, type: { type: "string", enum: ["image", "video", "audio"] }, role: { type: "string" }, label: { type: "string" }, name: { type: "string" } } }, CreateJobRequest: { type: "object", required: ["capability"], properties: { capability: { $ref: "#/components/schemas/GenerationCapability" }, prompt: { type: "string", description: "Prompt text. Required for image.generate unless promptAssembly is supplied." }, inputUrls: { type: "array", items: { type: "string", format: "uri" }, description: "Reference image URLs for image capabilities." }, imageUrls: { type: "array", items: { type: "string", format: "uri" }, description: "Alias for image input URLs." }, inputAssetIds: { type: "array", items: { type: "string" } }, materials: { type: "array", items: { $ref: "#/components/schemas/PromptMaterial" } }, settings: { type: "object", description: "Video settings for video.generate.", properties: { ratio: { type: "string", enum: ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9", "adaptive"] }, duration: { type: "integer", minimum: 4, maximum: 15 }, resolution: { type: "string", enum: ["480p", "720p", "1080p"] } } }, width: { type: "integer", example: 1440 }, height: { type: "integer", example: 2560 }, scale: { type: "number", minimum: 1, maximum: 100, description: "Jimeng text influence for image.generate and detail strength for image.upscale." }, force_single: { type: "boolean" }, quality: { type: "string", enum: ["low", "medium", "high"], description: "EvoLink image quality for image.generate and image.inpaint." }, resolution: { type: "string", enum: ["4k", "8k"], description: "Upscale resolution for image.upscale." }, seed: { type: "integer" }, priority: { type: "integer", minimum: -100, maximum: 100 }, webhookUrl: { type: "string", format: "uri" }, idempotencyKey: { type: "string", description: "Optional body-level idempotency key. Header Idempotency-Key is preferred." } } }, RegisterAssetRequest: { type: "object", required: ["url"], properties: { url: { type: "string", format: "uri" }, name: { type: "string" }, kind: { type: "string", enum: ["image", "video", "mask", "reference", "other"] }, tags: { type: "array", items: { type: "string" } } } }, WebhookPayload: { type: "object", required: ["event", "job"], properties: { event: { type: "string", example: "generation.succeeded" }, job: { $ref: "#/components/schemas/GenerationJob" } } } } }, paths: { "/api/v1/capabilities": { get: { summary: "List generation capabilities", responses: { "200": jsonResponse("Capabilities and active providers") } } }, "/api/v1/assets": { get: { summary: "List assets visible to the authenticated API client", responses: { "200": jsonResponse("Assets", { type: "object", properties: { assets: { type: "array", items: { $ref: "#/components/schemas/Asset" } } } }) } }, post: { summary: "Upload files or register an external asset URL", requestBody: { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/RegisterAssetRequest" } }, "multipart/form-data": { schema: { type: "object", properties: { files: { type: "array", items: { type: "string", format: "binary" } } } } } } }, responses: { "201": jsonResponse("Created asset"), "400": errorResponse(), "401": errorResponse() } } }, "/api/v1/assets/{id}": { get: { summary: "Get one asset visible to the authenticated API client", parameters: [pathId()], responses: { "200": jsonResponse("Asset", { type: "object", properties: { asset: { $ref: "#/components/schemas/Asset" } } }), "404": errorResponse() } } }, "/api/v1/assets/{id}/download": { get: { summary: "Download an output or uploaded asset", parameters: [pathId()], responses: { "200": { description: "Binary file", headers: { "Content-Disposition": { schema: { type: "string" } }, "Content-Length": { schema: { type: "string" } } }, content: { "application/octet-stream": { schema: { type: "string", format: "binary" } }, "image/png": { schema: { type: "string", format: "binary" } }, "image/jpeg": { schema: { type: "string", format: "binary" } }, "video/mp4": { schema: { type: "string", format: "binary" } } } }, "404": errorResponse() } } }, "/api/v1/jobs": { get: { summary: "List jobs for the authenticated API client", parameters: [ queryParam("status", { $ref: "#/components/schemas/GenerationStatus" }), queryParam("capability", { $ref: "#/components/schemas/GenerationCapability" }), queryParam("limit", { type: "integer", minimum: 1, maximum: 200 }), queryParam("before", { type: "string", format: "date-time" }) ], responses: { "200": jsonResponse("Jobs", { type: "object", properties: { jobs: { type: "array", items: { $ref: "#/components/schemas/GenerationJob" } } } }) } }, post: { summary: "Create a queued generation job", parameters: [ { name: "Idempotency-Key", in: "header", required: false, schema: { type: "string" }, description: "Reuse the same key for safe retries with the same request body." } ], requestBody: { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/CreateJobRequest" }, examples: { imageGenerate: { summary: "Image generation", value: { capability: "image.generate", prompt: "生成一张专业产品主图", width: 1440, height: 2560, webhookUrl: "https://example.com/zhinian/webhook" } }, videoGenerate: { summary: "Video generation", value: { capability: "video.generate", prompt: "生成一条 9:16 品牌短视频", settings: { ratio: "9:16", duration: 5, resolution: "720p" } } } } } } }, responses: { "202": jsonResponse("Queued job", { type: "object", properties: { job: { $ref: "#/components/schemas/GenerationJob" }, reused: { type: "boolean" } } }), "409": errorResponse() } } }, "/api/v1/jobs/{id}": { get: { summary: "Get one job", parameters: [pathId()], responses: { "200": jsonResponse("Job", { type: "object", properties: { job: { $ref: "#/components/schemas/GenerationJob" } } }), "404": errorResponse() } } }, "/api/v1/jobs/{id}/cancel": { post: { summary: "Cancel a queued or running job", parameters: [pathId()], responses: { "200": jsonResponse("Cancelled job", { type: "object", properties: { job: { $ref: "#/components/schemas/GenerationJob" } } }), "404": errorResponse() } } } } }); } function pathId() { return { name: "id", in: "path", required: true, schema: { type: "string" } }; } function queryParam(name: string, schema: Record) { return { name, in: "query", required: false, schema }; } function jsonResponse(description: string, schema: Record = { type: "object", additionalProperties: true }) { return { description, content: { "application/json": { schema } } }; } function errorResponse() { return jsonResponse("Error", { $ref: "#/components/schemas/ErrorResponse" }); }