openapi: 3.1.0 info: title: Civitai Orchestration API version: 'v2' description: | Submit AI generation workflows — image, video, audio, language, and LoRA training — through a single contract. The Orchestration API races multiple providers and engines behind one workflow surface and delivers results via webhooks or polling. Authenticate with a Bearer token issued at civitai.com. contact: name: Civitai Developer Support url: https://developer.civitai.com/orchestration/ termsOfService: https://civitai.com/content/tos license: name: Civitai Terms of Service url: https://civitai.com/content/tos servers: - url: https://orchestration.civitai.com description: Civitai Orchestration API security: - BearerAuth: [] tags: - name: Workflows description: Submit and manage generation workflows. - name: Blobs description: Upload and reference blobs for inputs and outputs. paths: /v2/consumer/workflows: post: operationId: submitWorkflow summary: Submit Workflow tags: [Workflows] description: Submit a new workflow composed of one or more steps. Each step references a recipe such as an image, video, audio, or training generator. requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/WorkflowRequest' } responses: '202': description: Workflow accepted for processing. content: application/json: schema: { $ref: '#/components/schemas/Workflow' } '400': { $ref: '#/components/responses/BadRequest' } '401': { $ref: '#/components/responses/Unauthorized' } '402': description: Insufficient Buzz balance. content: application/json: schema: { $ref: '#/components/schemas/Error' } '429': { $ref: '#/components/responses/RateLimited' } get: operationId: queryWorkflows summary: Query Workflows tags: [Workflows] parameters: - { name: take, in: query, schema: { type: integer, default: 20, maximum: 100 } } - { name: cursor, in: query, schema: { type: string } } - { name: tags, in: query, schema: { type: array, items: { type: string } } } - { name: status, in: query, schema: { type: string, enum: [unassigned, preparing, processing, succeeded, failed, expired, canceled] } } responses: '200': description: Page of workflows. content: application/json: schema: type: object properties: items: type: array items: { $ref: '#/components/schemas/Workflow' } nextCursor: { type: string } /v2/consumer/workflows/{workflowId}: parameters: - { name: workflowId, in: path, required: true, schema: { type: string } } get: operationId: getWorkflow summary: Get Workflow tags: [Workflows] responses: '200': description: Workflow status and outputs. content: application/json: schema: { $ref: '#/components/schemas/Workflow' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updateWorkflow summary: Update Workflow tags: [Workflows] requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/WorkflowUpdate' } responses: '200': description: Updated workflow. content: application/json: schema: { $ref: '#/components/schemas/Workflow' } patch: operationId: patchWorkflow summary: Patch Workflow tags: [Workflows] requestBody: required: true content: application/json-patch+json: schema: type: array items: { type: object } responses: '200': description: Patched workflow. content: application/json: schema: { $ref: '#/components/schemas/Workflow' } delete: operationId: deleteWorkflow summary: Delete Workflow tags: [Workflows] responses: '204': { description: Deleted. } /v2/consumer/blobs: post: operationId: uploadBlob summary: Upload Blob tags: [Blobs] description: Upload a blob (image, video, audio) with built-in NSFW moderation. requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: { type: string, format: binary } moderate: { type: boolean, default: true } responses: '201': description: Uploaded blob. content: application/json: schema: { $ref: '#/components/schemas/Blob' } /v2/consumer/blobs/upload-url: get: operationId: getBlobUploadUrl summary: Get Blob Upload URL tags: [Blobs] parameters: - { name: mimeType, in: query, required: true, schema: { type: string } } - { name: sizeBytes, in: query, schema: { type: integer } } responses: '200': description: Presigned upload URL. content: application/json: schema: type: object properties: blobId: { type: string } uploadUrl: { type: string, format: uri } expiresAt: { type: string, format: date-time } headers: type: object additionalProperties: { type: string } /v2/consumer/blobs/{blobId}: parameters: - { name: blobId, in: path, required: true, schema: { type: string } } get: operationId: getBlob summary: Get Blob tags: [Blobs] responses: '200': description: Blob metadata and download URL. content: application/json: schema: { $ref: '#/components/schemas/Blob' } head: operationId: headBlob summary: Head Blob tags: [Blobs] description: Check blob existence and moderation status without downloading metadata. responses: '200': { description: Blob exists. } '404': { description: Blob not found. } /v2/consumer/blobs/{blobId}/refresh: post: operationId: refreshBlob summary: Refresh Blob URL tags: [Blobs] parameters: - { name: blobId, in: path, required: true, schema: { type: string } } responses: '200': description: Refreshed blob with new signed URL. content: application/json: schema: { $ref: '#/components/schemas/Blob' } components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: token description: Personal API token issued at https://civitai.com/user/account. responses: BadRequest: description: Invalid request. content: application/json: schema: { $ref: '#/components/schemas/Error' } Unauthorized: description: Missing or invalid bearer token. content: application/json: schema: { $ref: '#/components/schemas/Error' } NotFound: description: Resource not found. content: application/json: schema: { $ref: '#/components/schemas/Error' } RateLimited: description: Too many requests. content: application/json: schema: { $ref: '#/components/schemas/Error' } schemas: Error: type: object properties: code: { type: string } message: { type: string } traceId: { type: string } WorkflowRequest: type: object required: [steps] properties: tags: type: array items: { type: string } callbackUrl: type: string format: uri description: HTTPS callback URL for webhook delivery. callbackEvents: type: array items: type: string enum: [workflow:*, workflow:succeeded, workflow:failed, workflow:processing, workflow:expired, workflow:canceled, step:*, job:*] detailed: { type: boolean, default: false } steps: type: array items: { $ref: '#/components/schemas/WorkflowStep' } WorkflowUpdate: type: object properties: tags: type: array items: { type: string } status: type: string enum: [canceled] WorkflowStep: type: object required: [$type, input] properties: $type: type: string description: Recipe type — e.g. imageGen, videoGen, audioGen, textGen, training, upscale. enum: [imageGen, videoGen, audioGen, textGen, transcribe, tts, music, upscale, interpolate, training, comfy, moderation] name: { type: string } input: { $ref: '#/components/schemas/StepInput' } priority: type: string enum: [low, normal, high] StepInput: type: object description: Recipe-specific input. The shape depends on `$type`. Common image-gen properties shown. properties: engine: type: string description: Engine identifier — e.g. flux2, flux1, sdxl, sd1, z-image, qwen, seedream, grok, wan2.5, kling, ltx2, vidu, veo3, hunyuan. model: { type: string, description: 'AIR or model identifier, e.g. urn:air:sdxl:checkpoint:civitai:12345@67890' } prompt: { type: string } negativePrompt: { type: string } width: { type: integer } height: { type: integer } aspectRatio: { type: string } steps: { type: integer } cfgScale: { type: number } sampler: { type: string } seed: { type: integer } clipSkip: { type: integer } quantity: { type: integer, default: 1, maximum: 10 } additionalNetworks: type: array items: type: object properties: air: { type: string } strength: { type: number } images: type: array description: Input image blob IDs for img2img / video / editing. items: { type: string } duration: { type: number, description: 'Seconds, for video.' } fps: { type: integer } upscaler: { type: string } Workflow: type: object properties: id: { type: string } status: type: string enum: [unassigned, preparing, processing, succeeded, failed, expired, canceled] tags: type: array items: { type: string } createdAt: { type: string, format: date-time } startedAt: { type: string, format: date-time } completedAt: { type: string, format: date-time } cost: type: object properties: base: { type: integer, description: Buzz cost. } total: { type: integer } currency: { type: string, enum: [BUZZ] } steps: type: array items: { $ref: '#/components/schemas/WorkflowStepResult' } WorkflowStepResult: type: object properties: name: { type: string } $type: { type: string } status: { type: string } startedAt: { type: string, format: date-time } completedAt: { type: string, format: date-time } jobs: type: array items: { $ref: '#/components/schemas/Job' } Job: type: object properties: id: { type: string } status: { type: string } startedAt: { type: string, format: date-time } completedAt: { type: string, format: date-time } result: type: object properties: blobs: type: array items: type: object properties: blobId: { type: string } url: { type: string, format: uri } mimeType: { type: string } width: { type: integer } height: { type: integer } durationMs: { type: integer } nsfwLevel: { type: integer } Blob: type: object properties: id: { type: string } mimeType: { type: string } sizeBytes: { type: integer } url: { type: string, format: uri } urlExpiresAt: { type: string, format: date-time } sha256: { type: string } nsfwLevel: { type: integer } nsfwReason: { type: string } createdAt: { type: string, format: date-time }