211 lines
12 KiB
JSON
211 lines
12 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "Chorus OpenAPI",
|
|
"version": "1.0.0",
|
|
"description": "Asynchronous text and image generation for existing controlled Chorus users. Submission never calls an upstream provider synchronously."
|
|
},
|
|
"servers": [{"url": "/"}],
|
|
"security": [{"APIKeyAuth": []}],
|
|
"paths": {
|
|
"/openapi/v1/openapi.json": {
|
|
"get": {
|
|
"operationId": "getOpenAPISpecification",
|
|
"responses": {
|
|
"200": {"description": "OpenAPI 3.1 document", "content": {"application/json": {"schema": {"type": "object"}}}},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations/text": {
|
|
"post": {
|
|
"operationId": "createTextGeneration",
|
|
"parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/TextGenerationRequest"}}}
|
|
},
|
|
"responses": {
|
|
"200": {"description": "Idempotent replay", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Generation"}}}},
|
|
"202": {"description": "Generation accepted", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Generation"}}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"409": {"$ref": "#/components/responses/Conflict"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"},
|
|
"503": {"$ref": "#/components/responses/Unavailable"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations/image": {
|
|
"post": {
|
|
"operationId": "createImageGeneration",
|
|
"description": "Multipart fields are prompt, metadata, and exactly one files[client_id] part for every image declared by metadata. image_generate has no file parts; image_edit requires at least one image and exactly one primary image.",
|
|
"parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"multipart/form-data": {
|
|
"schema": {
|
|
"type": "object",
|
|
"required": ["prompt", "metadata"],
|
|
"properties": {
|
|
"prompt": {"type": "string"},
|
|
"metadata": {"type": "string", "contentMediaType": "application/json", "contentSchema": {"$ref": "#/components/schemas/ImageMetadata"}}
|
|
},
|
|
"additionalProperties": {"type": "string", "format": "binary"}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {"description": "Idempotent replay", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Generation"}}}},
|
|
"202": {"description": "Generation accepted", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Generation"}}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"409": {"$ref": "#/components/responses/Conflict"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"},
|
|
"503": {"$ref": "#/components/responses/Unavailable"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations": {
|
|
"get": {
|
|
"operationId": "listGenerations",
|
|
"parameters": [
|
|
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200}},
|
|
{"name": "cursor", "in": "query", "schema": {"type": "string", "minLength": 1}}
|
|
],
|
|
"responses": {
|
|
"200": {"description": "Generation history", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GenerationPage"}}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations/{id}": {
|
|
"get": {
|
|
"operationId": "getGeneration",
|
|
"parameters": [{"$ref": "#/components/parameters/GenerationID"}],
|
|
"responses": {
|
|
"200": {"description": "Generation detail", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GenerationDetail"}}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"404": {"$ref": "#/components/responses/NotFound"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations/{id}/inputs/{inputID}": {
|
|
"get": {
|
|
"operationId": "getGenerationInput",
|
|
"parameters": [{"$ref": "#/components/parameters/GenerationID"}, {"$ref": "#/components/parameters/InputID"}],
|
|
"responses": {
|
|
"200": {"description": "Original input file", "content": {"image/png": {}, "image/jpeg": {}, "image/webp": {}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"404": {"$ref": "#/components/responses/NotFound"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations/{id}/outputs/{outputID}": {
|
|
"get": {
|
|
"operationId": "getGenerationOutput",
|
|
"parameters": [{"$ref": "#/components/parameters/GenerationID"}, {"$ref": "#/components/parameters/OutputID"}],
|
|
"responses": {
|
|
"200": {"description": "Original output file", "content": {"image/png": {}, "image/jpeg": {}, "image/webp": {}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"404": {"$ref": "#/components/responses/NotFound"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"}
|
|
}
|
|
}
|
|
},
|
|
"/openapi/v1/generations/{id}/outputs/{outputID}/thumbnail": {
|
|
"get": {
|
|
"operationId": "getGenerationOutputThumbnail",
|
|
"parameters": [{"$ref": "#/components/parameters/GenerationID"}, {"$ref": "#/components/parameters/OutputID"}],
|
|
"responses": {
|
|
"200": {"description": "Output thumbnail", "content": {"image/png": {}, "image/jpeg": {}, "image/webp": {}}},
|
|
"400": {"$ref": "#/components/responses/BadRequest"},
|
|
"401": {"$ref": "#/components/responses/Unauthorized"},
|
|
"404": {"$ref": "#/components/responses/NotFound"},
|
|
"429": {"$ref": "#/components/responses/TooManyRequests"}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"securitySchemes": {
|
|
"APIKeyAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "Chorus API Key"}
|
|
},
|
|
"parameters": {
|
|
"IdempotencyKey": {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128, "pattern": "^[!-~](?:[ -~]{6,126}[!-~])?$"}},
|
|
"GenerationID": {"name": "id", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64", "minimum": 1}},
|
|
"InputID": {"name": "inputID", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64", "minimum": 1}},
|
|
"OutputID": {"name": "outputID", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64", "minimum": 1}}
|
|
},
|
|
"responses": {
|
|
"BadRequest": {"description": "Invalid request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}},
|
|
"Unauthorized": {"description": "Missing or invalid API key", "headers": {"WWW-Authenticate": {"schema": {"type": "string"}}, "X-Request-ID": {"schema": {"type": "string"}}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}},
|
|
"NotFound": {"description": "Resource not found", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}},
|
|
"Conflict": {"description": "Idempotency key conflict", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}},
|
|
"TooManyRequests": {"description": "User or API key fixed-window rate limit exceeded", "headers": {"Retry-After": {"required": true, "schema": {"type": "integer", "minimum": 1}}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}},
|
|
"Unavailable": {"description": "Generation route unavailable", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}}
|
|
},
|
|
"schemas": {
|
|
"TextGenerationRequest": {"type": "object", "additionalProperties": false, "required": ["prompt"], "properties": {"prompt": {"type": "string", "minLength": 1}}},
|
|
"ImageMetadata": {
|
|
"type": "object", "additionalProperties": false, "required": ["capability", "role_rule", "images"],
|
|
"properties": {
|
|
"capability": {"type": "string", "enum": ["image_generate", "image_edit"]},
|
|
"role_rule": {"type": "string"},
|
|
"images": {"type": "array", "items": {"$ref": "#/components/schemas/ImageInput"}}
|
|
}
|
|
},
|
|
"ImageInput": {
|
|
"type": "object", "additionalProperties": false, "required": ["client_id", "position", "role", "note"],
|
|
"properties": {
|
|
"client_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,64}$"},
|
|
"position": {"type": "integer", "minimum": 0},
|
|
"role": {"type": "string", "enum": ["primary", "reference"]},
|
|
"note": {"type": "string", "maxLength": 500}
|
|
}
|
|
},
|
|
"Generation": {
|
|
"type": "object", "required": ["id", "kind", "status", "terminal", "user_prompt", "created_at"],
|
|
"properties": {
|
|
"id": {"type": "integer", "format": "int64"},
|
|
"kind": {"type": "string", "enum": ["text", "image"]},
|
|
"status": {"type": "string", "enum": ["pending", "running", "succeeded", "failed"]},
|
|
"terminal": {"type": "boolean"},
|
|
"user_prompt": {"type": "string"},
|
|
"error_code": {"type": ["string", "null"]},
|
|
"error_message": {"type": ["string", "null"]},
|
|
"created_at": {"type": "string", "format": "date-time"},
|
|
"started_at": {"type": ["string", "null"], "format": "date-time"},
|
|
"completed_at": {"type": ["string", "null"], "format": "date-time"}
|
|
}
|
|
},
|
|
"GenerationDetail": {
|
|
"allOf": [
|
|
{"$ref": "#/components/schemas/Generation"},
|
|
{"type": "object", "required": ["inputs", "outputs"], "properties": {"role_rule": {"type": ["string", "null"]}, "inputs": {"type": "array", "items": {"$ref": "#/components/schemas/GenerationInput"}}, "outputs": {"type": "array", "items": {"$ref": "#/components/schemas/GenerationOutput"}}}}
|
|
]
|
|
},
|
|
"GenerationInput": {
|
|
"type": "object",
|
|
"properties": {"id": {"type": "integer", "format": "int64"}, "position": {"type": "integer"}, "role": {"type": "string"}, "note": {"type": ["string", "null"]}, "name": {"type": "string"}, "mime_type": {"type": "string"}, "size_bytes": {"type": "integer"}, "width": {"type": ["integer", "null"]}, "height": {"type": ["integer", "null"]}, "url": {"type": "string"}}
|
|
},
|
|
"GenerationOutput": {
|
|
"type": "object",
|
|
"properties": {"id": {"type": "integer", "format": "int64"}, "kind": {"type": "string"}, "text": {"type": "string"}, "mime_type": {"type": ["string", "null"]}, "size_bytes": {"type": ["integer", "null"]}, "width": {"type": ["integer", "null"]}, "height": {"type": ["integer", "null"]}, "url": {"type": "string"}, "thumbnail_url": {"type": "string"}, "created_at": {"type": "string", "format": "date-time"}}
|
|
},
|
|
"GenerationPage": {"type": "object", "required": ["items", "next_cursor", "has_more"], "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Generation"}}, "next_cursor": {"type": "string"}, "has_more": {"type": "boolean"}}},
|
|
"ErrorEnvelope": {"type": "object", "additionalProperties": false, "required": ["error"], "properties": {"error": {"type": "object", "additionalProperties": true, "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}
|
|
}
|
|
}
|
|
}
|