Civitai Orchestration API

Submit AI generation workflows — image, video, audio, language, and LoRA training — through a single contract at `https://orchestration.civitai.com`. Races multiple providers and engines (Flux 1/2, SDXL, SD1, Z-Image, Qwen, Seedream, Grok, WAN 2.1-2.7, Kling, LTX2, Vidu, Veo 3, HunyuanVideo) behind one workflow API. Includes blob upload with NSFW moderation, presigned URLs, in-order serialized webhooks (`workflow:succeeded`, `workflow:failed`, etc.), and Buzz-metered billing. Bearer-token authenticated.

Civitai Orchestration API is one of 3 APIs that Civitai publishes on the APIs.io network, described by a machine-readable OpenAPI specification.

This API exposes 6 machine-runnable capabilities that can be deployed as REST, MCP, or Agent Skill surfaces via Naftiko and 1 JSON Schema definition.

Tagged areas include AI, Artificial Intelligence, Image Generation, Video Generation, and Audio Generation. The published artifact set on APIs.io includes API documentation, authentication docs, an OpenAPI specification, sample payloads, 6 Naftiko capability specs, and 1 JSON Schema.

Documentation

Specifications

Examples

Schemas & Data

Other Resources

OpenAPI Specification

civitai-orchestration-api-openapi.yml Raw ↑
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 }