{
  "info": {
    "name": "RunComfy API \u2014 ComfyUI, AI Image & Video Generator, LoRA Training",
    "description": "Run ComfyUI workflows in the cloud, build an AI image generator or AI video generator with RunComfy APIs for Seedance 2.5, Wan 3.0, Wan 2.2, FLUX 2, LTX 2.5 and Seedream 5.0, and train LoRAs on GPU with AI Toolkit.\n\n## Quickstart\n\n1. Fork this collection into your own workspace.\n2. Get a token from [RunComfy Profile](https://www.runcomfy.com/profile). Set `runcomfy_api_token` in a private/local environment; keep shared values empty.\n3. Run **Search models**, **Get model input schema**, or **List ComfyUI deployments** first.\n4. Configure the relevant model input or workflow overrides, then send one submission request. Paid requests require `allow_paid_requests=true` in your local environment.\n5. The submission script saves the returned ID locally for the matching status/result requests. Poll status until complete before retrieving output URLs. Re-sending a submission creates another job.\n\nThe default model example is FLUX.1 Kontext Pro image editing. Select another current model ID and use its own input schema for Seedance, Wan, LTX, Seedream, Kling, Nano Banana, or other AI image models and AI video models. Available AI image models, AI video models and pricing are listed on the live Models page. Training support is determined by RunComfy Trainer and is separate from image and video API support.\n\n## API families\n\n- [ComfyUI workflows](https://www.runcomfy.com/comfyui-workflows): [Workflow API quickstart](https://docs.runcomfy.com/serverless/quickstart). These examples use the current v2 workflow endpoints.\n- [AI image models and AI video models](https://www.runcomfy.com/models): [Model API quickstart](https://docs.runcomfy.com/model-apis/quickstart).\n- [GPU LoRA training](https://www.runcomfy.com/trainer/ai-toolkit): [Trainer API quickstart](https://docs.runcomfy.com/trainer-apis/quickstart).\n- [RunComfy MCP](https://docs.runcomfy.com/mcp/quickstart): connect assistants to `https://mcp.runcomfy.com/mcp`.\n\nAuthenticate requests with your RunComfy API token. Use publicly accessible HTTPS URLs for these model file-input examples. Dataset uploads use multipart form data. Supply an existing READY dataset and a complete reviewed AI Toolkit YAML configuration before starting training. Inference and training consume RunComfy credits.\n",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{runcomfy_api_token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "serverless_base_url",
      "value": "https://api.runcomfy.net",
      "type": "string"
    },
    {
      "key": "model_base_url",
      "value": "https://model-api.runcomfy.net",
      "type": "string"
    },
    {
      "key": "trainer_base_url",
      "value": "https://trainer-api.runcomfy.net",
      "type": "string"
    },
    {
      "key": "model_search",
      "value": "wan",
      "type": "string"
    },
    {
      "key": "model_limit",
      "value": "100",
      "type": "string"
    },
    {
      "key": "model_offset",
      "value": "0",
      "type": "string"
    },
    {
      "key": "model_id",
      "value": "blackforestlabs/flux-1-kontext/pro/edit",
      "type": "string"
    },
    {
      "key": "model_input_json",
      "value": "",
      "type": "string"
    },
    {
      "key": "deployment_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "workflow_overrides_json",
      "value": "{}",
      "type": "string"
    },
    {
      "key": "model_request_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "workflow_request_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "dataset_name",
      "value": "my_lora_dataset",
      "type": "string"
    },
    {
      "key": "dataset_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "training_config_yaml",
      "value": "",
      "type": "string"
    },
    {
      "key": "gpu_type",
      "value": "ADA_80_PLUS",
      "type": "string"
    },
    {
      "key": "training_job_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "allow_paid_requests",
      "value": "false",
      "type": "string"
    },
    {
      "key": "runcomfy_api_token",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "1. Start here \u2014 account and model discovery",
      "description": "Read-only requests to validate your token and select a model or saved ComfyUI deployment.",
      "item": [
        {
          "name": "Get RunComfy balance",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{serverless_base_url}}/prod/v2/balance",
            "description": "Check the wallet shared by workflow, model and training jobs. [Balance documentation](https://docs.runcomfy.com/account/balance)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Search models \u2014 Seedance, Wan, FLUX, LTX, Seedream",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/models?search={{model_search}}&limit={{model_limit}}&offset={{model_offset}}",
            "description": "Set model_search to a model family such as Seedance, Wan, FLUX, LTX, Seedream, Kling or Nano Banana. Inspect IDs, model pages and base pricing in the response. [Catalog API](https://docs.runcomfy.com/model-apis/model-catalog-endpoints)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "List model categories",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/models/categories",
            "description": "Discover supported categories, including image and video capabilities."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Get model input schema",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/models/{{model_id}}",
            "description": "Use the exact model_id, including its slashes. The returned input schema determines valid fields for your selected model."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('model_id')) { console.warn('Request skipped: set model_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "List ComfyUI deployments",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{serverless_base_url}}/prod/v2/deployments",
            "description": "Find your saved ComfyUI deployments and choose a deployment_id."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "List LoRA training datasets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/datasets",
            "description": "Find existing datasets and their names and readiness state. [Dataset API](https://docs.runcomfy.com/trainer-apis/async-queue-endpoints-datasets)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "2. Model API \u2014 image and video requests",
      "description": "Submit once, poll status, then retrieve outputs. Models have different input schemas. [Model quickstart](https://docs.runcomfy.com/model-apis/quickstart).",
      "item": [
        {
          "name": "Run FLUX Kontext image edit \u2014 billable",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/models/{{model_id}}",
            "description": "Runnable FLUX.1 Kontext Pro example from the API quickstart. If you change model_id, replace the body with the selected model schema. Sending this request consumes RunComfy credits.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"prompt\": \"Make the subject hold an orange umbrella while keeping the composition natural.\",\n  \"image_url\": \"https://playgrounds-storage-public.runcomfy.net/tools/7063/media-files/usecase1-1-input.webp\",\n  \"seed\": 81030369,\n  \"aspect_ratio\": \"16:9\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('model_id')) { console.warn('Request skipped: set model_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (String(pm.variables.get('allow_paid_requests')) !== 'true') { console.warn('Request skipped: this request consumes RunComfy credits. Review inputs and pricing, then set allow_paid_requests=true locally to run it.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) { const value = pm.response.json().request_id; if (value) pm.environment.set('model_request_id', value); }"
                ]
              }
            }
          ]
        },
        {
          "name": "Run selected image or video model \u2014 billable",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/models/{{model_id}}",
            "description": "Set model_input_json to a JSON object matching Get model input schema. Use this for Seedance, Wan, LTX, Seedream or any other supported image or video endpoint.",
            "body": {
              "mode": "raw",
              "raw": "{{model_input_json}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('model_id')) { console.warn('Request skipped: set model_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (!pm.variables.get('model_input_json')) { console.warn('Request skipped: set model_input_json in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (String(pm.variables.get('allow_paid_requests')) !== 'true') { console.warn('Request skipped: this request consumes RunComfy credits. Review inputs and pricing, then set allow_paid_requests=true locally to run it.'); pm.execution.skipRequest(); }",
                  "const input = JSON.parse(pm.variables.get('model_input_json')); if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('model_input_json must be a JSON object.');",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) { const value = pm.response.json().request_id; if (value) pm.environment.set('model_request_id', value); }"
                ]
              }
            }
          ]
        },
        {
          "name": "Get model request status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/requests/{{model_request_id}}/status",
            "description": "Poll the ID returned by submission. Typical states: in_queue, in_progress, completed, failed or cancelled."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('model_request_id')) { console.warn('Request skipped: set model_request_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Get model result and cost",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{model_base_url}}/v1/requests/{{model_request_id}}/result?include_cost=true",
            "description": "Retrieve hosted output URLs and reported cost after completion."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('model_request_id')) { console.warn('Request skipped: set model_request_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "3. ComfyUI workflow API \u2014 GPU deployments",
      "description": "Run your own saved ComfyUI workflow with deployment-specific inputs. [Workflow API](https://docs.runcomfy.com/serverless/async-queue-endpoints).",
      "item": [
        {
          "name": "Get ComfyUI deployment and input payload",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{serverless_base_url}}/prod/v2/deployments/{{deployment_id}}?includes=payload&includes=readme",
            "description": "Inspect the stored workflow and README before choosing node IDs for overrides."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('deployment_id')) { console.warn('Request skipped: set deployment_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Run saved ComfyUI workflow \u2014 billable",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{serverless_base_url}}/prod/v2/deployments/{{deployment_id}}/inference",
            "description": "Set workflow_overrides_json to a JSON object keyed by existing node IDs. The default empty object runs saved inputs unchanged. Inspect the deployment payload first.",
            "body": {
              "mode": "raw",
              "raw": "{\"overrides\": {{workflow_overrides_json}}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('deployment_id')) { console.warn('Request skipped: set deployment_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (String(pm.variables.get('allow_paid_requests')) !== 'true') { console.warn('Request skipped: this request consumes RunComfy credits. Review inputs and pricing, then set allow_paid_requests=true locally to run it.'); pm.execution.skipRequest(); }",
                  "const overrides = JSON.parse(pm.variables.get('workflow_overrides_json')); if (!overrides || typeof overrides !== 'object' || Array.isArray(overrides)) throw new Error('workflow_overrides_json must be a JSON object.');",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) { const value = pm.response.json().request_id; if (value) pm.environment.set('workflow_request_id', value); }"
                ]
              }
            }
          ]
        },
        {
          "name": "Get ComfyUI request status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{serverless_base_url}}/prod/v2/deployments/{{deployment_id}}/requests/{{workflow_request_id}}/status",
            "description": "Poll the previously submitted workflow request."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('deployment_id')) { console.warn('Request skipped: set deployment_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (!pm.variables.get('workflow_request_id')) { console.warn('Request skipped: set workflow_request_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Get ComfyUI result",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{serverless_base_url}}/prod/v2/deployments/{{deployment_id}}/requests/{{workflow_request_id}}/result",
            "description": "Retrieve output files after the workflow completes."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('deployment_id')) { console.warn('Request skipped: set deployment_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (!pm.variables.get('workflow_request_id')) { console.warn('Request skipped: set workflow_request_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "4. LoRA training \u2014 datasets and GPU jobs",
      "description": "Create a dataset, upload matching media/captions, wait for READY, and submit a reviewed AI Toolkit config. [Trainer documentation](https://docs.runcomfy.com/trainer-apis/quickstart).",
      "item": [
        {
          "name": "Create LoRA training dataset",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/datasets",
            "description": "Create dataset metadata. The response name is used in the mounted dataset path. Files are uploaded separately.",
            "body": {
              "mode": "raw",
              "raw": "{{dataset_request_json}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('dataset_name')) { console.warn('Request skipped: set dataset_name in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "pm.variables.set('dataset_request_json', JSON.stringify({name: pm.variables.get('dataset_name')}));",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) { const value = pm.response.json().id; if (value) pm.environment.set('dataset_id', value); }"
                ]
              }
            }
          ]
        },
        {
          "name": "Upload training image, video or caption",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/datasets/{{dataset_id}}/upload",
            "description": "Choose one local file in Body \u2192 form-data \u2192 file. Upload media and a matching .txt caption with the same base name. Direct uploads support files up to 150 MB.",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": null,
                  "description": "Choose one image, video, or matching .txt caption from your computer."
                }
              ]
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('dataset_id')) { console.warn('Request skipped: set dataset_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Get dataset readiness",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/datasets/{{dataset_id}}/status",
            "description": "Wait until the dataset is READY before submitting training."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('dataset_id')) { console.warn('Request skipped: set dataset_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Start AI Toolkit LoRA training \u2014 billable",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/ai-toolkit/jobs",
            "description": "Set training_config_yaml to the full reviewed YAML configuration. Reference /app/ai-toolkit/datasets/{dataset_name}, set training_folder=/app/ai-toolkit/output, and choose a supported gpu_type. The script JSON-encodes multiline YAML.",
            "body": {
              "mode": "raw",
              "raw": "{{training_request_json}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('training_config_yaml')) { console.warn('Request skipped: set training_config_yaml in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (!pm.variables.get('gpu_type')) { console.warn('Request skipped: set gpu_type in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "if (String(pm.variables.get('allow_paid_requests')) !== 'true') { console.warn('Request skipped: this request consumes RunComfy credits. Review inputs and pricing, then set allow_paid_requests=true locally to run it.'); pm.execution.skipRequest(); }",
                  "pm.variables.set('training_request_json', JSON.stringify({config_file_format:'yaml', config_file:pm.variables.get('training_config_yaml'), gpu_type:pm.variables.get('gpu_type'), gpu_count:1}));",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) { const value = pm.response.json().id; if (value) pm.environment.set('training_job_id', value); }"
                ]
              }
            }
          ]
        },
        {
          "name": "Get LoRA training status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/ai-toolkit/jobs/{{training_job_id}}/status",
            "description": "Check training progress. STOPPED may mean completion or preemption: inspect step progress and results."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('training_job_id')) { console.warn('Request skipped: set training_job_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        },
        {
          "name": "Get LoRA checkpoints and sample results",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": "{{trainer_base_url}}/prod/v1/trainers/ai-toolkit/jobs/{{training_job_id}}/result",
            "description": "Retrieve checkpoints, configuration and sample URLs for the specified training job."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "try {",
                  "if (!pm.variables.get('training_job_id')) { console.warn('Request skipped: set training_job_id in your local environment before sending this request.'); pm.execution.skipRequest(); }",
                  "} catch (error) {",
                  "  console.warn('Request skipped: ' + error.message);",
                  "  pm.execution.skipRequest();",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Successful API response', () => pm.expect(pm.response.code).to.be.within(200, 299));"
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
