{
  "openapi": "3.1.0",
  "info": {
    "title": "pre.dev API",
    "description": "Public REST API for software specifications, browser automation, and credit balance. Base URL: https://api.pre.dev. MCP is documented separately at https://docs.pre.dev/mcp/tools.",
    "version": "1.1.0",
    "contact": {
      "name": "pre.dev Support",
      "url": "https://pre.dev",
      "email": "support@pre.dev"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://pre.dev/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.pre.dev",
      "description": "Production API Server"
    }
  ],
  "security": [
    {
      "apiKeyAuth": []
    },
    {
      "xApiKey": []
    }
  ],
  "paths": {
    "/fast-spec": {
      "post": {
        "operationId": "generateFastSpec",
        "tags": [
          "Specifications"
        ],
        "summary": "Generate a fast spec",
        "description": "Supply JSON text or one multipart file. Use async=true for durable ID-based polling. Duplicate submissions create separate jobs; no idempotency key is supported.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpecRequest"
              },
              "example": {
                "input": "Build a team task manager with projects, assignees, and due dates.",
                "async": true
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/FileUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Full result for synchronous requests; specId and pending status for asynchronous requests.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/SpecResponse"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": [
                                "completed"
                              ]
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/AsyncResponse"
                    }
                  ]
                },
                "examples": {
                  "submitted": {
                    "summary": "Async submission",
                    "value": {
                      "specId": "507f1f77bcf86cd799439011",
                      "status": "pending"
                    }
                  },
                  "completed": {
                    "summary": "Synchronous completion (illustrative)",
                    "value": {
                      "_id": "507f1f77bcf86cd799439011",
                      "endpoint": "fast_spec",
                      "status": "completed",
                      "success": true,
                      "progress": 100,
                      "codingAgentSpecMarkdown": "# Task manager\n\nProjects, assignments, and due dates."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_input": {
                    "summary": "No input or file",
                    "value": {
                      "error": "Invalid input",
                      "message": "Please provide either a file upload or input text describing your spec"
                    }
                  },
                  "invalid_doc_urls": {
                    "summary": "docURLs is not an array",
                    "value": {
                      "error": "Invalid docURLs",
                      "message": "docURLs must be an array of strings"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Insufficient balance or a billing gate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Insufficient credits",
                  "message": "You have insufficient credits to generate a spec. Please purchase more credits or upgrade your plan.",
                  "generationsAvailable": 0
                }
              }
            }
          },
          "403": {
            "description": "Access or trial eligibility denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Free trials exhausted",
                  "message": "You have used all 3 of your free API trials. Please subscribe to Solo Premium to continue.",
                  "requiresSubscription": true,
                  "trialsUsed": 3,
                  "maxTrials": 3
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to generate fast spec",
                  "message": "Generation failed. Retry the request."
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "source": "curl --fail-with-body https://api.pre.dev/fast-spec \\\n  -H \"Authorization: Bearer $PREDEV_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"input\": \"Build a team task manager with projects, assignees, and due dates.\",\n  \"async\": true\n}'"
          }
        ]
      }
    },
    "/deep-spec": {
      "post": {
        "operationId": "generateDeepSpec",
        "tags": [
          "Specifications"
        ],
        "summary": "Generate a deep spec",
        "description": "Supply JSON text or one multipart file. Use async=true for durable ID-based polling. Duplicate submissions create separate jobs; no idempotency key is supported.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpecRequest"
              },
              "example": {
                "input": "Build a team task manager with projects, assignees, and due dates.",
                "async": true
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/FileUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Full result for synchronous requests; specId and pending status for asynchronous requests.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/SpecResponse"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": [
                                "completed"
                              ]
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/AsyncResponse"
                    }
                  ]
                },
                "examples": {
                  "submitted": {
                    "summary": "Async submission",
                    "value": {
                      "specId": "507f1f77bcf86cd799439011",
                      "status": "pending"
                    }
                  },
                  "completed": {
                    "summary": "Synchronous completion (illustrative)",
                    "value": {
                      "_id": "507f1f77bcf86cd799439011",
                      "endpoint": "deep_spec",
                      "status": "completed",
                      "success": true,
                      "progress": 100,
                      "codingAgentSpecMarkdown": "# Task manager\n\nProjects, assignments, and due dates."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_input": {
                    "summary": "No input or file",
                    "value": {
                      "error": "Invalid input",
                      "message": "Please provide either a file upload or input text describing your spec"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Insufficient balance or a billing gate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Insufficient credits",
                  "message": "You have insufficient credits to generate a spec. Please purchase more credits or upgrade your plan.",
                  "generationsAvailable": 0
                }
              }
            }
          },
          "403": {
            "description": "Access or trial eligibility denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Free trials exhausted",
                  "message": "You have used all 3 of your free API trials. Please subscribe to Solo Premium to continue.",
                  "requiresSubscription": true,
                  "trialsUsed": 3,
                  "maxTrials": 3
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to generate deep spec",
                  "message": "Generation failed. Retry the request."
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "source": "curl --fail-with-body https://api.pre.dev/deep-spec \\\n  -H \"Authorization: Bearer $PREDEV_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"input\": \"Build a team task manager with projects, assignees, and due dates.\",\n  \"async\": true\n}'"
          }
        ]
      }
    },
    "/spec-status/{specId}": {
      "get": {
        "operationId": "getSpecStatus",
        "tags": [
          "Specifications"
        ],
        "summary": "Get a spec",
        "description": "Poll until status is completed or failed. Includes available artifacts; progress alone is not a completion signal.",
        "parameters": [
          {
            "name": "specId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "24-character record ID.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current spec record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpecResponse"
                },
                "example": {
                  "_id": "507f1f77bcf86cd799439011",
                  "endpoint": "fast_spec",
                  "status": "completed",
                  "success": true,
                  "progress": 100,
                  "input": "Build a team task manager with projects, assignees, and due dates.",
                  "codingAgentSpecMarkdown": "# Task manager\n\nProjects, assignments, and due dates."
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid request ID",
                  "message": "Please provide a valid request ID"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Access or trial eligibility denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid API Key or Domain"
                }
              }
            }
          },
          "404": {
            "description": "Record unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Request not found",
                  "message": "The specified request ID does not exist or you do not have access to it"
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to fetch request status",
                  "message": "Retry the request."
                }
              }
            }
          }
        }
      }
    },
    "/list-specs": {
      "get": {
        "operationId": "listSpecs",
        "tags": [
          "Specifications"
        ],
        "summary": "List specs",
        "description": "Newest first. Summary records omit Markdown, JSON, graphs, and credit details. Unrecognized status or endpoint filters are ignored.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "endpoint",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "fast_spec",
                "deep_spec"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "processing",
                "completed",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated spec summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSpecsResponse"
                },
                "example": {
                  "specs": [
                    {
                      "_id": "507f1f77bcf86cd799439011",
                      "endpoint": "fast_spec",
                      "status": "completed",
                      "success": true,
                      "input": "Build a team task manager with projects, assignees, and due dates."
                    }
                  ],
                  "total": 1,
                  "hasMore": false
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Access or trial eligibility denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid API Key or Domain"
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to list specs",
                  "message": "Retry the request."
                }
              }
            }
          }
        }
      }
    },
    "/find-specs": {
      "get": {
        "operationId": "findSpecs",
        "tags": [
          "Specifications"
        ],
        "summary": "Search specs",
        "description": "Newest first. Summary records omit Markdown, JSON, graphs, and credit details. Unrecognized status or endpoint filters are ignored.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "description": "Case-insensitive regular expression matched against spec input. Invalid syntax returns 500."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "endpoint",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "fast_spec",
                "deep_spec"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "processing",
                "completed",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated spec summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSpecsResponse"
                },
                "example": {
                  "specs": [
                    {
                      "_id": "507f1f77bcf86cd799439011",
                      "endpoint": "deep_spec",
                      "status": "completed",
                      "success": true,
                      "input": "Add Stripe billing to the task manager."
                    }
                  ],
                  "total": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid search query",
                  "message": "Please provide a search query parameter"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Access or trial eligibility denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid API Key or Domain"
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to search specs",
                  "message": "Retry the request."
                }
              }
            }
          }
        }
      }
    },
    "/get-plan": {
      "get": {
        "operationId": "getPlan",
        "tags": [
          "Specifications"
        ],
        "summary": "Get a project's plan",
        "description": "The verified plan of a project you own, by specId or projectId: what it is for, each feature's status from pre.dev's checks, progress, Ready to launch, and where screens, API routes and stored data live in the code. Pass exactly one of specId or projectId.",
        "parameters": [
          {
            "name": "specId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "A specId from fast-spec or deep-spec.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "projectId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "A pre.dev project ID.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "markdown"
              ],
              "default": "json",
              "description": "markdown returns the Markdown alone as text/markdown."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The plan, or plan null while the project has none yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetPlanResponse"
                },
                "example": {
                  "projectId": "507f191e810c19729de860ea",
                  "specId": null,
                  "plan": {
                    "projectId": "507f191e810c19729de860ea",
                    "name": "Recipe Box",
                    "computedAt": "2026-10-02T14:00:00.000Z",
                    "codeVersion": {
                      "tree": "a36fd496594c6417aa3ab8c6e534f2d7537d4a2e",
                      "short": "a36fd49"
                    },
                    "intent": {
                      "text": "Recipe Box is for people who keep a small collection of recipes. They can browse recipes, add new ones, and mark a recipe as cooked.",
                      "proposedByPredev": true,
                      "removedSince": []
                    },
                    "progress": {
                      "basis": "features",
                      "built": 2,
                      "provenWorking": 1,
                      "total": 3,
                      "left": 1,
                      "percent": 67,
                      "proposed": 0
                    },
                    "features": [
                      {
                        "id": "feat_1a2b3c4d5e6f7a8b",
                        "name": "Browse recipes",
                        "status": "works",
                        "statusText": "Works, checked 2 h ago",
                        "scope": "confirmed",
                        "addedByAgent": false,
                        "stories": {
                          "done": 2,
                          "total": 2
                        },
                        "counted": true,
                        "removedParts": []
                      },
                      {
                        "id": "feat_2b3c4d5e6f7a8b9c",
                        "name": "Add a recipe",
                        "status": "built_not_checked",
                        "statusText": "Built, not checked yet",
                        "scope": "confirmed",
                        "addedByAgent": false,
                        "stories": {
                          "done": 1,
                          "total": 1
                        },
                        "counted": true,
                        "removedParts": []
                      },
                      {
                        "id": "feat_3c4d5e6f7a8b9c0d",
                        "name": "Mark a recipe as cooked",
                        "status": "planned",
                        "statusText": "Planned, not built",
                        "scope": "confirmed",
                        "addedByAgent": false,
                        "stories": {
                          "done": 0,
                          "total": 1
                        },
                        "counted": true,
                        "removedParts": []
                      }
                    ],
                    "readyToLaunch": {
                      "ready": false,
                      "items": [
                        {
                          "id": "features_built",
                          "label": "Everything you asked for is built",
                          "state": "needs_fix",
                          "detail": "1 of 3 features is not built yet: Mark a recipe as cooked",
                          "fix": null
                        },
                        {
                          "id": "data_persisted",
                          "label": "Data is saved beyond one browser",
                          "state": "ok",
                          "detail": "Saved in a SQLite file on the server",
                          "fix": null
                        },
                        {
                          "id": "live_current",
                          "label": "Not published yet",
                          "state": "needs_fix",
                          "detail": null,
                          "fix": {
                            "action": "Publish",
                            "how": "Publish the project from its page on pre.dev."
                          }
                        }
                      ]
                    },
                    "appMap": {
                      "codeVersion": "a36fd49",
                      "mappedAt": "2026-10-02T13:59:00.000Z",
                      "screens": {
                        "count": 2,
                        "items": [
                          {
                            "name": "Home",
                            "path": "/",
                            "anchor": "server/index.js:22"
                          },
                          {
                            "name": "New Recipe",
                            "path": "/new",
                            "anchor": "server/index.js:34"
                          }
                        ]
                      },
                      "endpoints": {
                        "count": 1,
                        "items": [
                          {
                            "name": "POST /new",
                            "anchor": "server/index.js:38",
                            "writes": true
                          }
                        ]
                      },
                      "storage": {
                        "count": 1,
                        "items": [
                          {
                            "name": "Recipes",
                            "kind": "table (SQL)",
                            "where": "in the database",
                            "anchor": "server/db.js"
                          }
                        ]
                      }
                    },
                    "lastRun": {
                      "runId": "6abfb8ac0e1670226a1ecd9b",
                      "kind": "chat",
                      "endedAt": "2026-10-02T13:56:00.000Z",
                      "codeVersion": {
                        "before": "e82c333",
                        "after": "a36fd49"
                      },
                      "filesChanged": {
                        "count": 1,
                        "paths": [
                          "server/views.js"
                        ]
                      },
                      "appMap": {
                        "added": [
                          {
                            "kind": "screen",
                            "name": "/new"
                          }
                        ],
                        "removed": [],
                        "changed": []
                      }
                    }
                  },
                  "markdown": "# Plan for Recipe Box\n\nComputed 2026-10-02 14:00 UTC at code version a36fd49.\n\n## What it is for\n\nRecipe Box is for people who keep a small collection of recipes. ...\n\n## Progress\n\n2 of 3 features built (67%), 1 proven working by a check, 1 left.\n..."
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                },
                "example": "# Plan for Recipe Box\n\nComputed 2026-10-02 14:00 UTC at code version a36fd49.\n\n## What it is for\n\nRecipe Box is for people who keep a small collection of recipes. ...\n\n## Progress\n\n2 of 3 features built (67%), 1 proven working by a check, 1 left.\n..."
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "one_id": {
                    "summary": "Neither or both IDs",
                    "value": {
                      "error": "Invalid request",
                      "message": "Pass exactly one of specId (from fast-spec or deep-spec) or projectId"
                    }
                  },
                  "invalid_id": {
                    "summary": "Malformed ID",
                    "value": {
                      "error": "Invalid ID",
                      "message": "Please provide a valid specId or projectId"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not your project, no project yet, or plans are turned off.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not your project or spec",
                    "value": {
                      "error": "Project not found",
                      "message": "The project does not exist or you do not have access to it"
                    }
                  },
                  "no_project": {
                    "summary": "The spec has no project yet",
                    "value": {
                      "error": "No project yet",
                      "message": "The spec has no project yet. Check /spec-status and try again once it is processing."
                    }
                  },
                  "not_available": {
                    "summary": "Plans are turned off",
                    "value": {
                      "error": "Not available",
                      "message": "Plans are turned off right now."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to fetch plan",
                  "message": "Retry the request."
                }
              }
            }
          }
        }
      }
    },
    "/credits-balance": {
      "get": {
        "operationId": "getCreditsBalance",
        "tags": [
          "Account"
        ],
        "summary": "Get credit balance",
        "description": "Returns the effective account or organization balance. Fractional credits are possible.",
        "responses": {
          "200": {
            "description": "Credit balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditsBalanceResponse"
                },
                "example": {
                  "success": true,
                  "creditsRemaining": 412.5
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  },
                  "no_subscription": {
                    "summary": "Personal key without a paid plan",
                    "value": {
                      "error": "Authentication failed",
                      "message": "An active subscription is required for this endpoint"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Access or trial eligibility denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid API Key or Domain"
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to retrieve credits balance",
                  "message": "Retry the request."
                }
              }
            }
          }
        }
      }
    },
    "/browser-agent": {
      "post": {
        "operationId": "runTask",
        "tags": [
          "Browser Agents"
        ],
        "summary": "Run browser tasks",
        "description": "Default: synchronous JSON. async=true returns an ID. stream=true takes precedence and returns SSE task_event, task_result, done (full result), or error. A matching retry key returns JSON even when stream=true. A disconnected client does not cancel execution.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional user-scoped 24-hour retry lookup. Reuse only for the same logical submission; concurrent first requests can still duplicate work."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              },
              "example": {
                "tasks": [
                  {
                    "url": "https://example.com",
                    "instruction": "Extract the main page heading.",
                    "output": {
                      "type": "object",
                      "properties": {
                        "heading": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "heading"
                      ]
                    },
                    "mode": "extract",
                    "maxSteps": 10,
                    "maxDurationSeconds": 60
                  }
                ],
                "async": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch result, asynchronous ID, or SSE stream. Inspect Content-Type before parsing. A done batch can contain failed tasks; inspect each task status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "examples": {
                  "submitted": {
                    "summary": "Async submission",
                    "value": {
                      "id": "507f1f77bcf86cd799439011",
                      "total": 1,
                      "completed": 0,
                      "results": [],
                      "totalCreditsUsed": 0,
                      "status": "processing"
                    }
                  },
                  "completed": {
                    "summary": "Completed run (illustrative)",
                    "value": {
                      "id": "507f1f77bcf86cd799439011",
                      "total": 1,
                      "completed": 1,
                      "results": [
                        {
                          "url": "https://example.com",
                          "status": "SUCCESS",
                          "data": {
                            "heading": "Example Domain"
                          },
                          "creditsUsed": 0.1
                        }
                      ],
                      "totalCreditsUsed": 0.1,
                      "status": "completed"
                    }
                  }
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                },
                "example": "event: task_event\ndata: {\"taskIndex\":0,\"type\":\"navigation\",\"timestamp\":1788739200000,\"data\":{\"url\":\"https://example.com\"}}\n\nevent: task_result\ndata: {\"taskIndex\":0,\"status\":\"SUCCESS\",\"data\":{\"title\":\"Example Domain\"},\"creditsUsed\":0.1}\n\nevent: done\ndata: {\"id\":\"64b7f3e1c2a9d5e6f8a01234\",\"status\":\"completed\",\"total\":1,\"completed\":1,\"results\":[{\"status\":\"SUCCESS\",\"data\":{\"title\":\"Example Domain\"},\"creditsUsed\":0.1}],\"totalCreditsUsed\":0.1}\n\n"
              }
            }
          },
          "400": {
            "description": "Invalid task input, malformed or unresolvable URL, missing instructions/output schema, or oversized batch. No work is started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_instruction": {
                    "summary": "Task has no instruction or output schema",
                    "value": {
                      "error": "Task 1: Describe what the agent should do, or provide an output schema.",
                      "code": "MISSING_INSTRUCTION",
                      "taskIndex": 0,
                      "field": "instruction"
                    }
                  },
                  "invalid_url": {
                    "summary": "Task URL rejected",
                    "value": {
                      "error": "Task 1: Enter a full website URL, such as https://example.com.",
                      "code": "INVALID_URL",
                      "taskIndex": 0,
                      "field": "url"
                    }
                  },
                  "batch_too_large": {
                    "summary": "Too many tasks",
                    "value": {
                      "error": "A batch can contain at most 1000 tasks.",
                      "code": "BATCH_TOO_LARGE"
                    }
                  },
                  "url_unreachable": {
                    "summary": "Domain has no DNS address",
                    "value": {
                      "error": "Task 1: We couldn't find the website example.invalid. Check the URL and try again. No tasks were started.",
                      "code": "URL_UNREACHABLE",
                      "taskIndex": 0,
                      "field": "url"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Insufficient balance or a billing gate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_credits": {
                    "summary": "Not enough credits",
                    "value": {
                      "error": "Need ~0.5 credits, have 0.00. Buy more to continue.",
                      "code": "INSUFFICIENT_CREDITS",
                      "actionUrl": "https://pre.dev/projects/browser-agents?upgrade=credits"
                    }
                  },
                  "subscription_required": {
                    "summary": "Free allowance used",
                    "value": {
                      "error": "Free accounts can spend up to 2 credits on browser agents. You've used 2.00. Subscribe to keep going.",
                      "code": "SUBSCRIPTION_REQUIRED",
                      "actionUrl": "https://pre.dev/projects/browser-agents?upgrade=subscribe"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate or inflight limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Rate limit: 600 requests/minute. Try again in a minute.",
                  "code": "RATE_LIMITED"
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Internal server error"
                }
              }
            }
          },
          "503": {
            "description": "Streaming capacity unavailable, or temporary DNS verification failure (URL_CHECK_UNAVAILABLE). No tasks start when input verification fails.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "url_check_unavailable": {
                    "summary": "Website verification unavailable",
                    "value": {
                      "error": "Website verification timed out or is temporarily unavailable. Please try again. No tasks were started.",
                      "code": "URL_CHECK_UNAVAILABLE",
                      "field": "url"
                    }
                  },
                  "stream_capacity": {
                    "summary": "Streaming capacity full (stream: true)",
                    "value": {
                      "error": "SSE capacity exceeded on this pod (5000/5000). Retry with async=true and poll GET /browser-agent/:id."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "source": "curl --fail-with-body https://api.pre.dev/browser-agent \\\n  -H \"Authorization: Bearer $PREDEV_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"tasks\": [\n    {\n      \"url\": \"https://example.com\",\n      \"instruction\": \"Extract the main page heading.\",\n      \"output\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"heading\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"heading\"\n        ]\n      },\n      \"mode\": \"extract\",\n      \"maxSteps\": 10,\n      \"maxDurationSeconds\": 60\n    }\n  ],\n  \"async\": true\n}'"
          }
        ]
      }
    },
    "/browser-agent/{id}": {
      "get": {
        "operationId": "getRun",
        "tags": [
          "Browser Agents"
        ],
        "summary": "Get browser task status",
        "description": "Use batch status for completion, then each task status for success. The completed counter includes placeholder slots.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "24-character record ID.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "includeEvents",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch with available results and optional events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "examples": {
                  "processing": {
                    "summary": "Processing with placeholders",
                    "value": {
                      "id": "507f1f77bcf86cd799439011",
                      "total": 1,
                      "completed": 1,
                      "results": [
                        {
                          "url": "https://example.com",
                          "status": "RUNNING",
                          "queuePosition": 0,
                          "attempts": 1
                        }
                      ],
                      "totalCreditsUsed": 0,
                      "status": "processing"
                    }
                  },
                  "completed": {
                    "summary": "Completed run (illustrative)",
                    "value": {
                      "id": "507f1f77bcf86cd799439011",
                      "total": 1,
                      "completed": 1,
                      "results": [
                        {
                          "url": "https://example.com",
                          "status": "SUCCESS",
                          "data": {
                            "heading": "Example Domain"
                          },
                          "creditsUsed": 0.1
                        }
                      ],
                      "totalCreditsUsed": 0.1,
                      "status": "completed"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "invalid batch id"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Record unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "batch not found"
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Authentication failed",
                  "message": "Retry the request."
                }
              }
            }
          }
        }
      }
    },
    "/list-browser-agents": {
      "get": {
        "operationId": "listRuns",
        "tags": [
          "Browser Agents"
        ],
        "summary": "List browser runs",
        "description": "Newest first; use the detail endpoint for complete task results.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "processing",
                "completed",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated run summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListBatchesResponse"
                },
                "example": {
                  "batches": [
                    {
                      "id": "507f1f77bcf86cd799439011",
                      "name": "Example heading",
                      "status": "completed",
                      "total": 1,
                      "completed": 1,
                      "totalCreditsUsed": 0.1,
                      "createdAt": "2026-09-27T12:00:00.000Z",
                      "completedAt": "2026-09-27T12:00:21.000Z",
                      "results": []
                    }
                  ],
                  "total": 1,
                  "hasMore": false
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Internal server error"
                }
              }
            }
          }
        }
      }
    },
    "/browser-agent-status": {
      "get": {
        "operationId": "browserAgentStatus",
        "tags": [
          "Browser Agents"
        ],
        "summary": "Get account queue status",
        "description": "Snapshot of your queue and current inflight cap; does not reserve capacity.",
        "responses": {
          "200": {
            "description": "Account queue snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserAgentStatus"
                },
                "example": {
                  "running": 2,
                  "claimed": 0,
                  "pending": 3,
                  "total": 5,
                  "cap": 25
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Internal server error"
                }
              }
            }
          }
        }
      }
    },
    "/browser-agent-capacity": {
      "get": {
        "operationId": "browserAgentCapacity",
        "tags": [
          "Browser Agents"
        ],
        "summary": "Get service capacity",
        "description": "Advisory service diagnostics. Prefer /browser-agent-status for admission decisions.",
        "responses": {
          "200": {
            "description": "Service capacity snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserCapacity"
                },
                "example": {
                  "totalActive": 64,
                  "maxSandboxes": 200,
                  "perUserCap": 50,
                  "pending": 12,
                  "running": 60,
                  "claimed": 4,
                  "failed": 0,
                  "utilization": 32,
                  "oldestQueuedAgeMs": 1800
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Request failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Internal server error"
                }
              }
            }
          }
        }
      }
    },
    "/browser-agent/{id}/ws": {
      "get": {
        "operationId": "getLiveBrowser",
        "tags": [
          "Browser Agents"
        ],
        "summary": "Get a live browser URL",
        "description": "Returns a credential-bearing WebSocket URL for live JPEG frames. Availability depends on the execution path. No browser input control or recorded playback.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "24-character record ID.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Connect to the returned WebSocket URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveBrowserResponse"
                },
                "example": {
                  "url": "wss://browser-worker.example/ws/507f1f77bcf86cd799439011?token=3f1c0b9e2d4a7c58"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "invalid batch id"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Record unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Unknown batch",
                    "value": {
                      "error": "batch not found"
                    }
                  },
                  "no_stream": {
                    "summary": "No live stream for this batch",
                    "value": {
                      "error": "live stream not available"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/browser-agent/{id}/stream": {
      "get": {
        "operationId": "streamBrowserAgent",
        "tags": [
          "Browser Agents"
        ],
        "summary": "Watch an existing browser run",
        "description": "SSE: snapshot, batch_meta, task_event, task_result, done, error. The done payload is status only, unlike POST streaming. Already finished runs emit snapshot then done. No replay cursor; reconnect for a fresh snapshot, or poll after interruption.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "24-character record ID.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SSE stream. Errors after headers arrive as error events, not new HTTP status codes.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                },
                "example": "event: snapshot\ndata: {\"id\":\"64b7f3e1c2a9d5e6f8a01234\",\"status\":\"processing\",\"total\":1,\"completed\":1,\"results\":[{\"status\":\"PENDING\"}]}\n\nevent: batch_meta\ndata: {\"name\":\"Example lookup\",\"taskNames\":[\"Read title\"]}\n\nevent: task_result\ndata: {\"taskIndex\":0,\"status\":\"SUCCESS\",\"data\":{\"title\":\"Example Domain\"},\"creditsUsed\":0.1}\n\nevent: done\ndata: {\"status\":\"completed\"}\n\n"
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "invalid batch id"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or ineligible authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "summary": "No key sent",
                    "value": {
                      "error": "Missing API key",
                      "message": "Please provide an API key via Authorization: Bearer <token> header or x-api-key header"
                    }
                  },
                  "invalid_key": {
                    "summary": "Unknown key",
                    "value": {
                      "error": "Authentication failed",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Record unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "batch not found"
                }
              }
            }
          },
          "503": {
            "description": "Streaming capacity unavailable; retry later or use polling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "SSE capacity exceeded on this pod (5000/5000). Fall back to polling GET /browser-agent/:id."
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "xApiKey": []
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "Your pre.dev workspace API key (pdk_...) from Integrations, Built-in tab: https://pre.dev/projects/integrations?tab=built-in"
      },
      "xApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Alternative to Authorization: Bearer."
      }
    },
    "schemas": {
      "SpecRequest": {
        "type": "object",
        "required": [
          "input"
        ],
        "properties": {
          "input": {
            "type": "string",
            "description": "Project requirements. Include goals, users, constraints, and acceptance criteria.",
            "minLength": 1
          },
          "currentContext": {
            "type": "string",
            "description": "Existing system or specification as text; this is not a spec ID."
          },
          "docURLs": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Public documentation URLs; retrieval and downloadable archives are best effort."
          },
          "async": {
            "type": "boolean",
            "default": false,
            "description": "Return {specId, status: pending} immediately. Poll GET /spec-status/{specId}."
          }
        }
      },
      "FileUploadRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "description": "One PDF, DOC, DOCX, TXT, JPEG, or PNG file, at most 20 MiB. Send the matching MIME type.",
            "format": "binary"
          },
          "input": {
            "type": "string",
            "description": "Requirements, used alone or with the file.",
            "minLength": 1
          },
          "currentContext": {
            "type": "string",
            "description": "Existing system context as text."
          },
          "docURLs": {
            "type": "string",
            "description": "JSON-encoded array of public documentation URLs.",
            "example": "[\"https://example.com/docs\"]"
          },
          "async": {
            "type": "boolean",
            "default": false
          }
        },
        "anyOf": [
          {
            "required": [
              "file"
            ]
          },
          {
            "required": [
              "input"
            ]
          }
        ]
      },
      "SpecResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "_id": {
            "type": "string",
            "description": "24-character record ID.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "endpoint": {
            "type": "string",
            "enum": [
              "fast_spec",
              "deep_spec"
            ],
            "description": "Which endpoint was used"
          },
          "input": {
            "type": "string",
            "description": "Original input text provided"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ]
          },
          "success": {
            "type": "boolean",
            "description": "Whether the request succeeded"
          },
          "uploadedFileShortUrl": {
            "anyOf": [
              {
                "type": "string",
                "description": "Short URL for uploaded file (if file was uploaded)"
              },
              {
                "type": "null"
              }
            ]
          },
          "uploadedFileName": {
            "anyOf": [
              {
                "type": "string",
                "description": "Name of uploaded file (if file was uploaded)"
              },
              {
                "type": "null"
              }
            ]
          },
          "humanSpecUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "URL where the human-readable spec is hosted (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "totalHumanHours": {
            "anyOf": [
              {
                "type": "number",
                "description": "Estimated total hours for a human to implement the spec (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "architectureInfographicUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "URL to a visual architecture infographic/diagram for the specification (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "codingAgentSpecUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "URL where the coding agent spec format is hosted (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "codingAgentSpecJson": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CodingAgentSpecJson",
                "description": "Structured JSON spec optimized for AI coding assistants (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "codingAgentSpecMarkdown": {
            "anyOf": [
              {
                "type": "string",
                "description": "Markdown spec optimized for AI coding assistants (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "humanSpecJson": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/HumanSpecJson",
                "description": "Full structured JSON spec with hours, personas, and roles (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "humanSpecMarkdown": {
            "anyOf": [
              {
                "type": "string",
                "description": "Full markdown spec with all details for human review (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "executionTime": {
            "anyOf": [
              {
                "type": "integer",
                "description": "Processing time in milliseconds (only when completed or failed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "predevUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "pre.dev project URL (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "zippedDocsUrls": {
            "anyOf": [
              {
                "type": "array",
                "description": "Array of scraped documentation archives (only when completed). Empty array if no docURLs provided or scraping fails",
                "items": {
                  "$ref": "#/components/schemas/ZippedDocsUrl"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "errorMessage": {
            "anyOf": [
              {
                "type": "string",
                "description": "Error description (only when failed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "progress": {
            "anyOf": [
              {
                "type": "number",
                "description": "Completion percentage (0-100) while processing"
              },
              {
                "type": "null"
              }
            ]
          },
          "creditsUsed": {
            "anyOf": [
              {
                "type": "number",
                "description": "Measured credit usage; estimates are not fixed charges."
              },
              {
                "type": "null"
              }
            ]
          },
          "userFlowGraph": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpecGraph",
                "description": "User flow graph with nodes representing user stories/flows and edges showing navigation paths (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "architectureGraph": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpecGraph",
                "description": "System architecture graph with C1/C2 level nodes and their relationships (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "enrichedTechStack": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SpecEnrichedTechStackItem"
                },
                "description": "Enriched tech stack with detailed reasons, descriptions, and alternatives for each technology (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "progressMessage": {
            "anyOf": [
              {
                "type": "string",
                "description": "Human-readable progress description (e.g. 'Generating architecture...')"
              },
              {
                "type": "null"
              }
            ]
          },
          "currentContext": {
            "anyOf": [
              {
                "type": "string",
                "description": "Existing context supplied with generation."
              },
              {
                "type": "null"
              }
            ]
          },
          "specSource": {
            "anyOf": [
              {
                "type": "string",
                "description": "Origin of the request, such as api or mcp."
              },
              {
                "type": "null"
              }
            ]
          },
          "docURLs": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "plan": {
            "$ref": "#/components/schemas/ProjectPlan",
            "description": "The project's verified plan, once the spec is completed and its project has something planned or built. Absent otherwise."
          }
        },
        "description": "Full specification/status record. Fields may be absent or null until available. Terminal status is completed or failed. executionTime is milliseconds."
      },
      "AsyncResponse": {
        "type": "object",
        "required": [
          "specId",
          "status"
        ],
        "properties": {
          "specId": {
            "type": "string",
            "description": "24-character record ID.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          }
        }
      },
      "StatusResponse": {
        "$ref": "#/components/schemas/SpecResponse"
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "Optional detail; not returned by every endpoint."
          },
          "code": {
            "type": "string",
            "description": "Machine-readable code when available."
          },
          "actionUrl": {
            "type": "string",
            "format": "uri"
          },
          "requiresSubscription": {
            "type": "boolean"
          },
          "trialsUsed": {
            "type": "integer"
          },
          "maxTrials": {
            "type": "integer"
          }
        },
        "additionalProperties": true
      },
      "InsufficientCreditsError": {
        "type": "object",
        "required": [
          "error",
          "message",
          "generationsAvailable"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "generationsAvailable": {
            "type": "number",
            "description": "Legacy field name containing the remaining credit balance, not a count of spec runs."
          }
        }
      },
      "ListSpecsResponse": {
        "type": "object",
        "required": [
          "specs",
          "total",
          "hasMore"
        ],
        "properties": {
          "specs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecSummary"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "ZippedDocsUrl": {
        "type": "object",
        "required": [
          "platform",
          "masterZipShortUrl"
        ],
        "properties": {
          "platform": {
            "type": "string",
            "description": "Hostname extracted from the documentation URL (e.g., 'stripe.com', 'docs.github.com')",
            "example": "stripe.com"
          },
          "masterZipShortUrl": {
            "type": "string",
            "format": "uri",
            "description": "Short URL to download the zipped documentation archive for this platform"
          },
          "masterMarkdownShortUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional short URL to consolidated markdown file for this platform"
          }
        }
      },
      "SpecCoreFunctionality": {
        "type": "object",
        "required": [
          "name",
          "description"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the core functionality"
          },
          "description": {
            "type": "string",
            "description": "Description of the functionality"
          },
          "priority": {
            "type": "string",
            "enum": [
              "High",
              "Medium",
              "Low"
            ],
            "description": "Priority level of the functionality"
          }
        }
      },
      "SpecTechStackItem": {
        "type": "object",
        "required": [
          "name",
          "category"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the technology"
          },
          "category": {
            "type": "string",
            "description": "Category of the technology (e.g., Frontend, Backend, Database)"
          }
        }
      },
      "SpecPersona": {
        "type": "object",
        "required": [
          "title",
          "description"
        ],
        "properties": {
          "title": {
            "type": "string",
            "description": "Title of the persona"
          },
          "description": {
            "type": "string",
            "description": "Description of the persona"
          },
          "primaryGoals": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Primary goals of the persona"
          },
          "painPoints": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Pain points of the persona"
          },
          "keyTasks": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Key tasks of the persona"
          }
        }
      },
      "SpecRole": {
        "type": "object",
        "required": [
          "name",
          "shortHand"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Full name of the role (e.g., Full Stack Developer)"
          },
          "shortHand": {
            "type": "string",
            "description": "Short abbreviation for the role (e.g., FSD)"
          }
        }
      },
      "CodingAgentSubTask": {
        "type": "object",
        "required": [
          "description",
          "complexity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Subtask identifier"
          },
          "description": {
            "type": "string",
            "description": "Description of the subtask"
          },
          "complexity": {
            "type": "string",
            "enum": [
              "S",
              "M",
              "L",
              "XL"
            ],
            "description": "Complexity estimate"
          }
        }
      },
      "CodingAgentStory": {
        "type": "object",
        "required": [
          "title",
          "subTasks"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Story identifier (e.g., US-001)"
          },
          "title": {
            "type": "string",
            "description": "Title of the user story"
          },
          "description": {
            "type": "string",
            "description": "Description of the user story"
          },
          "acceptanceCriteria": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of acceptance criteria"
          },
          "complexity": {
            "type": "string",
            "description": "Complexity estimate for the story"
          },
          "subTasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodingAgentSubTask"
            },
            "description": "List of subtasks for this story"
          }
        }
      },
      "CodingAgentMilestone": {
        "type": "object",
        "required": [
          "milestoneNumber",
          "description",
          "stories"
        ],
        "properties": {
          "milestoneNumber": {
            "type": "integer",
            "description": "Milestone number"
          },
          "description": {
            "type": "string",
            "description": "Description of the milestone"
          },
          "stories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodingAgentStory"
            },
            "description": "List of user stories in this milestone"
          }
        }
      },
      "CodingAgentSpecJson": {
        "type": "object",
        "required": [
          "executiveSummary",
          "coreFunctionalities",
          "techStack",
          "milestones"
        ],
        "description": "Simplified structured JSON for AI coding tools (excludes hours, personas, roles)",
        "properties": {
          "title": {
            "type": "string",
            "description": "Title of the specification"
          },
          "executiveSummary": {
            "type": "string",
            "description": "Executive summary of the project"
          },
          "coreFunctionalities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecCoreFunctionality"
            },
            "description": "List of core functionalities"
          },
          "techStack": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecTechStackItem"
            },
            "description": "Technology stack items"
          },
          "techStackGrouped": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Technology stack grouped by category"
          },
          "milestones": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodingAgentMilestone"
            },
            "description": "List of milestones"
          }
        }
      },
      "HumanSpecSubTask": {
        "type": "object",
        "required": [
          "description",
          "hours",
          "complexity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Subtask identifier"
          },
          "description": {
            "type": "string",
            "description": "Description of the subtask"
          },
          "hours": {
            "type": "number",
            "description": "Estimated hours for this subtask"
          },
          "complexity": {
            "type": "string",
            "description": "Complexity estimate"
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecRole"
            },
            "description": "Roles assigned to this subtask"
          }
        }
      },
      "HumanSpecStory": {
        "type": "object",
        "required": [
          "title",
          "hours",
          "subTasks"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Story identifier (e.g., US-001)"
          },
          "title": {
            "type": "string",
            "description": "Title of the user story"
          },
          "description": {
            "type": "string",
            "description": "Description of the user story"
          },
          "acceptanceCriteria": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of acceptance criteria"
          },
          "hours": {
            "type": "number",
            "description": "Estimated hours for this story"
          },
          "complexity": {
            "type": "string",
            "description": "Complexity estimate for the story"
          },
          "subTasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HumanSpecSubTask"
            },
            "description": "List of subtasks for this story"
          }
        }
      },
      "HumanSpecMilestone": {
        "type": "object",
        "required": [
          "milestoneNumber",
          "description",
          "hours",
          "stories"
        ],
        "properties": {
          "milestoneNumber": {
            "type": "integer",
            "description": "Milestone number"
          },
          "description": {
            "type": "string",
            "description": "Description of the milestone"
          },
          "hours": {
            "type": "number",
            "description": "Estimated hours for this milestone"
          },
          "stories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HumanSpecStory"
            },
            "description": "List of user stories in this milestone"
          }
        }
      },
      "HumanSpecJson": {
        "type": "object",
        "required": [
          "executiveSummary",
          "coreFunctionalities",
          "personas",
          "techStack",
          "milestones",
          "totalHours",
          "roles"
        ],
        "description": "Full structured JSON with hours, personas, and roles for human review",
        "properties": {
          "title": {
            "type": "string",
            "description": "Title of the specification"
          },
          "executiveSummary": {
            "type": "string",
            "description": "Executive summary of the project"
          },
          "coreFunctionalities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecCoreFunctionality"
            },
            "description": "List of core functionalities"
          },
          "personas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecPersona"
            },
            "description": "User personas"
          },
          "techStack": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecTechStackItem"
            },
            "description": "Technology stack items"
          },
          "techStackGrouped": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Technology stack grouped by category"
          },
          "milestones": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HumanSpecMilestone"
            },
            "description": "List of milestones with hours"
          },
          "totalHours": {
            "type": "number",
            "description": "Total estimated hours for the project"
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecRole"
            },
            "description": "Roles required for the project"
          }
        }
      },
      "CreditsBalanceResponse": {
        "type": "object",
        "required": [
          "success",
          "creditsRemaining"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the request was successful"
          },
          "creditsRemaining": {
            "type": [
              "number",
              "null"
            ],
            "description": "Remaining credits. `null` on plans without a credit limit."
          }
        }
      },
      "SpecGraphNode": {
        "type": "object",
        "required": [
          "id",
          "label"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the node"
          },
          "label": {
            "type": "string",
            "description": "Display label for the node"
          },
          "type": {
            "type": "string",
            "description": "Node category; values depend on the graph."
          },
          "description": {
            "type": "string",
            "description": "Description of the node"
          },
          "level": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "description": "Numeric flow depth or an architecture level such as C1 or C2, when available."
          },
          "hours": {
            "type": "number",
            "description": "Estimated hours for this node"
          }
        }
      },
      "SpecGraphEdge": {
        "type": "object",
        "required": [
          "source",
          "target"
        ],
        "properties": {
          "source": {
            "type": "string",
            "description": "Source node ID"
          },
          "target": {
            "type": "string",
            "description": "Target node ID"
          },
          "description": {
            "type": "string",
            "description": "Description of the relationship"
          },
          "edgeType": {
            "type": "string",
            "description": "Type of edge relationship"
          }
        }
      },
      "SpecGraph": {
        "type": "object",
        "required": [
          "nodes",
          "edges"
        ],
        "properties": {
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecGraphNode"
            },
            "description": "Array of graph nodes"
          },
          "edges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecGraphEdge"
            },
            "description": "Array of graph edges"
          }
        }
      },
      "SpecEnrichedTechStackItem": {
        "type": "object",
        "required": [
          "name",
          "useFor",
          "reason",
          "description"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the technology (e.g., React, PostgreSQL)"
          },
          "useFor": {
            "type": "string",
            "description": "Category label (e.g., Frontend, Backend, Database)"
          },
          "reason": {
            "type": "string",
            "description": "Why this technology was chosen for this specific project"
          },
          "description": {
            "type": "string",
            "description": "Technical description of what the technology does"
          },
          "link": {
            "type": "string",
            "format": "uri",
            "description": "Official website or documentation URL"
          },
          "helpfulLinks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL to helpful resource"
                },
                "description": {
                  "type": "string",
                  "description": "Description of the resource"
                }
              }
            },
            "description": "Array of helpful documentation and tutorial links"
          },
          "alternatives": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Name of the alternative technology"
                },
                "link": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL of the alternative technology"
                },
                "description": {
                  "type": "string",
                  "description": "Description of the alternative"
                }
              }
            },
            "description": "Array of alternative technologies that could be used instead"
          }
        }
      },
      "Task": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Full starting HTTP(S) URL. Domains must resolve to at least one IPv4 or IPv6 address.",
            "format": "uri"
          },
          "instruction": {
            "type": "string",
            "description": "Goal and constraints for the task."
          },
          "input": {
            "type": "object",
            "properties": {},
            "additionalProperties": {
              "type": "string"
            },
            "description": "Named string inputs available to the runner."
          },
          "output": {
            "type": "object",
            "properties": {},
            "additionalProperties": true,
            "description": "JSON Schema for extracted data. If omitted, the runner may infer a schema.",
            "minProperties": 1
          },
          "successCondition": {
            "type": "string",
            "description": "Natural-language completion check."
          },
          "mode": {
            "type": "string",
            "description": "auto chooses extraction when an output schema is provided; agent handles interaction.",
            "enum": [
              "auto",
              "extract",
              "agent"
            ],
            "default": "auto"
          },
          "maxSteps": {
            "type": "integer",
            "description": "Planning iteration budget. MCP accepts 1–50; use this range across clients. REST forwards the value without equivalent range validation.",
            "minimum": 1,
            "maximum": 50
          },
          "maxDurationSeconds": {
            "type": "integer",
            "description": "Wall-clock budget in seconds. MCP accepts 5–600; use this range across clients. Defaults vary by execution path.",
            "minimum": 5,
            "maximum": 600
          },
          "maxIterations": {
            "type": "integer",
            "description": "Legacy alias of maxSteps. If both are supplied, maxIterations takes precedence.",
            "deprecated": true
          },
          "timeoutMs": {
            "type": "integer",
            "description": "Legacy millisecond budget. If both are supplied, timeoutMs takes precedence over maxDurationSeconds.",
            "deprecated": true
          }
        },
        "description": "A full HTTP(S) URL and either nonblank instructions or a non-empty output schema are required. The entire batch is validated before billing or queueing.",
        "anyOf": [
          {
            "required": [
              "instruction"
            ],
            "properties": {
              "instruction": {
                "type": "string",
                "pattern": "\\S"
              }
            }
          },
          {
            "required": [
              "output"
            ]
          }
        ]
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "tasks"
        ],
        "properties": {
          "tasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            },
            "minItems": 1,
            "description": "One or more tasks. Default server limit is 1,000, configurable by deployment; BATCH_TOO_LARGE reports the active limit."
          },
          "concurrency": {
            "type": "integer",
            "description": "Requested parallelism; defaults to 5 and is clamped to 1–20. Account and service capacity may reduce effective parallelism.",
            "minimum": 1,
            "maximum": 20,
            "default": 5
          },
          "async": {
            "type": "boolean",
            "default": false,
            "description": "Return the batch ID immediately, then poll or attach to its stream."
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "Return SSE; takes precedence over async."
          },
          "idempotencyKey": {
            "type": "string",
            "description": "Optional retry lookup key. Idempotency-Key header takes precedence. User-scoped lookup lasts 24 hours; concurrent first requests are not atomically deduplicated."
          }
        }
      },
      "TaskResult": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "instruction": {
            "type": "string"
          },
          "input": {
            "type": "object",
            "properties": {},
            "additionalProperties": true
          },
          "output": {
            "type": "object",
            "properties": {},
            "additionalProperties": true
          },
          "status": {
            "type": "string",
            "description": "PENDING and RUNNING are status placeholders; all other listed values are terminal task outcomes.",
            "enum": [
              "PENDING",
              "RUNNING",
              "SUCCESS",
              "ERROR",
              "TIMEOUT",
              "BLOCKED",
              "CAPTCHA_FAILED",
              "LOOP",
              "NO_TARGET",
              "EXHAUSTED"
            ]
          },
          "data": {
            "description": "Extracted result; shape follows the requested or inferred schema. May be null or omitted."
          },
          "creditsUsed": {
            "type": "number",
            "description": "Settled task charge: every task keeps the 0.1-credit floor charged at submission; every status except ERROR and EXHAUSTED adds any usage above it."
          },
          "durationMs": {
            "type": "integer",
            "description": "Wall-clock task duration in milliseconds."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "attempts": {
            "type": "integer"
          },
          "queuePosition": {
            "anyOf": [
              {
                "type": "integer",
                "description": "Queue estimate; 0 when running."
              },
              {
                "type": "null"
              }
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunnerEvent"
            },
            "description": "Available timeline when includeEvents=true."
          }
        },
        "additionalProperties": true
      },
      "RunnerEvent": {
        "type": "object",
        "required": [
          "type",
          "timestamp"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Extensible event type, for example navigation, screenshot, plan, action, validation, waiting, done, or error."
          },
          "timestamp": {
            "type": "number",
            "description": "Unix timestamp in milliseconds."
          },
          "iteration": {
            "type": "integer"
          },
          "data": {
            "description": "Event-specific payload. Screenshot data is not guaranteed to be a URL."
          }
        },
        "additionalProperties": true
      },
      "BatchResult": {
        "type": "object",
        "required": [
          "id",
          "status",
          "results"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "24-character record ID.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "taskNames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total": {
            "type": "integer"
          },
          "completed": {
            "type": "integer",
            "description": "Counts result slots, including pending/running placeholders or nulls. Do not use this as the completion signal."
          },
          "results": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/TaskResult"
                },
                {
                  "type": "null"
                }
              ]
            },
            "description": "Ordered by task index. Slots can be null or partial until a result arrives."
          },
          "totalCreditsUsed": {
            "type": "number"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "failed"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "liveEvents": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/RunnerEvent"
              }
            },
            "description": "Per-task events when includeEvents=true and live events are available."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": true
      },
      "BrowserAgentStatus": {
        "type": "object",
        "properties": {
          "running": {
            "type": "integer"
          },
          "claimed": {
            "type": "integer"
          },
          "pending": {
            "type": "integer"
          },
          "total": {
            "type": "integer",
            "description": "Current inflight count reported by the queue snapshot."
          },
          "cap": {
            "type": "integer",
            "description": "Current account inflight limit, resolved by tier. Treat this as a snapshot, not a reservation."
          }
        },
        "additionalProperties": true
      },
      "SpecSummary": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "_id": {
            "type": "string",
            "description": "24-character record ID.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "endpoint": {
            "type": "string",
            "enum": [
              "fast_spec",
              "deep_spec"
            ],
            "description": "Which endpoint was used"
          },
          "input": {
            "type": "string",
            "description": "Original input text provided"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ]
          },
          "success": {
            "type": "boolean",
            "description": "Whether the request succeeded"
          },
          "uploadedFileShortUrl": {
            "anyOf": [
              {
                "type": "string",
                "description": "Short URL for uploaded file (if file was uploaded)"
              },
              {
                "type": "null"
              }
            ]
          },
          "uploadedFileName": {
            "anyOf": [
              {
                "type": "string",
                "description": "Name of uploaded file (if file was uploaded)"
              },
              {
                "type": "null"
              }
            ]
          },
          "executionTime": {
            "anyOf": [
              {
                "type": "integer",
                "description": "Processing time in milliseconds (only when completed or failed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "currentContext": {
            "anyOf": [
              {
                "type": "string",
                "description": "Existing context supplied with generation."
              },
              {
                "type": "null"
              }
            ]
          },
          "specSource": {
            "anyOf": [
              {
                "type": "string",
                "description": "Origin of the request, such as api or mcp."
              },
              {
                "type": "null"
              }
            ]
          },
          "errorMessage": {
            "anyOf": [
              {
                "type": "string",
                "description": "Error description (only when failed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "progress": {
            "anyOf": [
              {
                "type": "number",
                "description": "Completion percentage (0-100) while processing"
              },
              {
                "type": "null"
              }
            ]
          },
          "predevUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "pre.dev project URL (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "docURLs": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "zippedDocsUrls": {
            "anyOf": [
              {
                "type": "array",
                "description": "Array of scraped documentation archives (only when completed). Empty array if no docURLs provided or scraping fails",
                "items": {
                  "$ref": "#/components/schemas/ZippedDocsUrl"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "codingAgentSpecUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "URL where the coding agent spec format is hosted (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "humanSpecUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "URL where the human-readable spec is hosted (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          },
          "architectureInfographicUrl": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "description": "URL to a visual architecture infographic/diagram for the specification (only when completed)"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "description": "Summary only. Use GET /spec-status/{specId} for Markdown, JSON, graphs, totalHumanHours, creditsUsed, and progressMessage."
      },
      "BrowserGateError": {
        "type": "object",
        "required": [
          "error",
          "code"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "SUBSCRIPTION_REQUIRED",
              "INSUFFICIENT_CREDITS",
              "RATE_LIMITED",
              "QUEUE_FULL",
              "BATCH_TOO_LARGE"
            ]
          },
          "actionUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "BatchSummary": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "24-character record ID.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "taskNames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total": {
            "type": "integer"
          },
          "completed": {
            "type": "integer",
            "description": "Count of stored task results in this history response."
          },
          "results": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/TaskResult"
                },
                {
                  "type": "null"
                }
              ]
            },
            "description": "Compact preview, not a complete result set. Use GET /browser-agent/{id} for details."
          },
          "totalCreditsUsed": {
            "type": "number"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "failed"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": true
      },
      "ListBatchesResponse": {
        "type": "object",
        "required": [
          "batches",
          "total",
          "hasMore"
        ],
        "properties": {
          "batches": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "BrowserCapacity": {
        "type": "object",
        "properties": {
          "totalActive": {
            "type": "integer"
          },
          "maxSandboxes": {
            "type": "integer"
          },
          "perUserCap": {
            "type": "integer"
          },
          "pending": {
            "type": "integer"
          },
          "running": {
            "type": "integer"
          },
          "claimed": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "oldestQueuedAgeMs": {
            "type": "integer"
          },
          "utilization": {
            "type": "number",
            "description": "Reported utilization percentage."
          }
        },
        "description": "Advisory service diagnostics. Fields may change; perUserCap is a legacy global value, not your account limit. Use GET /browser-agent-status for your cap.",
        "additionalProperties": true
      },
      "LiveBrowserResponse": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Credential-bearing WebSocket URL. Keep private and use only for the requested batch.",
            "format": "uri"
          }
        }
      },
      "ProjectPlanFeature": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "statusText",
          "scope",
          "addedByAgent",
          "stories",
          "counted",
          "removedParts"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "The feature in the owner's words."
          },
          "status": {
            "type": "string",
            "enum": [
              "works",
              "built_not_checked",
              "changed_since_check",
              "needs_a_look",
              "not_working",
              "in_progress",
              "planned",
              "out_of_scope",
              "removed"
            ],
            "description": "From pre.dev's checks. works: a check of this feature passed at the current code. built_not_checked: the code is there, nothing has proven it. changed_since_check: its files changed after its check passed. needs_a_look: its check failed the last time it ran. not_working: its check keeps failing. in_progress, planned: not built yet. out_of_scope: set outside the project's scope, not counted. removed: taken out because the owner asked, not counted."
          },
          "statusText": {
            "type": "string",
            "description": "The words pre.dev shows, for example \"Works, checked 2 h ago\"."
          },
          "scope": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed",
              "out_of_scope"
            ],
            "description": "proposed: suggested by pre.dev and not counted until the owner confirms it."
          },
          "addedByAgent": {
            "type": "boolean"
          },
          "stories": {
            "type": "object",
            "required": [
              "done",
              "total"
            ],
            "properties": {
              "done": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            }
          },
          "counted": {
            "type": "boolean",
            "description": "Counted in progress."
          },
          "removedParts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Parts the owner asked to take out of this feature."
          },
          "partOf": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "id",
              "name"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "description": "Set on work added to a feature that was already built: the feature it belongs to. The addition counts as its own item, listed right after that feature, until it is built, then folds back into the feature. null on a feature."
          }
        }
      },
      "ProjectPlanLaunchItem": {
        "type": "object",
        "required": [
          "id",
          "label",
          "state",
          "detail",
          "fix"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "For example features_built, env_keys, data_persisted, sign_in, sample_data, publish_build, live_current, live_saves."
          },
          "label": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "ok",
              "needs_fix",
              "unknown",
              "not_needed"
            ]
          },
          "detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "fix": {
            "anyOf": [
              {
                "type": "object",
                "required": [
                  "action",
                  "how"
                ],
                "properties": {
                  "action": {
                    "type": "string"
                  },
                  "how": {
                    "type": "string",
                    "description": "What to do in plain words: where to click on pre.dev, or what to ask a coding agent to do."
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ProjectPlan": {
        "type": "object",
        "description": "A project's verified plan: what it is for, each feature's status from pre.dev's checks, progress, Ready to launch, where things live in the code, and the last change.",
        "required": [
          "projectId",
          "name",
          "computedAt",
          "codeVersion",
          "intent",
          "progress",
          "features",
          "readyToLaunch",
          "appMap",
          "lastRun"
        ],
        "properties": {
          "projectId": {
            "type": "string",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "codeVersion": {
            "type": "object",
            "required": [
              "tree",
              "short"
            ],
            "description": "The code version the plan was computed at; null before any code exists.",
            "properties": {
              "tree": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "short": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "intent": {
            "anyOf": [
              {
                "type": "object",
                "required": [
                  "text",
                  "proposedByPredev",
                  "removedSince"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "What the app is for, in one paragraph."
                  },
                  "proposedByPredev": {
                    "type": "boolean",
                    "description": "Proposed by pre.dev from the request and not edited by the owner yet."
                  },
                  "removedSince": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Taken out since, as the owner asked."
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "progress": {
            "type": "object",
            "required": [
              "basis",
              "built",
              "provenWorking",
              "total",
              "left",
              "percent",
              "proposed"
            ],
            "properties": {
              "basis": {
                "type": "string",
                "enum": [
                  "features",
                  "stories",
                  "none"
                ]
              },
              "built": {
                "type": "integer"
              },
              "provenWorking": {
                "type": "integer",
                "description": "Built and proven working by a check at the current code."
              },
              "total": {
                "type": "integer"
              },
              "left": {
                "type": "integer"
              },
              "percent": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100
              },
              "proposed": {
                "type": "integer",
                "description": "Suggested features, not counted until confirmed."
              }
            }
          },
          "features": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectPlanFeature"
            }
          },
          "readyToLaunch": {
            "anyOf": [
              {
                "type": "object",
                "required": [
                  "ready",
                  "items"
                ],
                "properties": {
                  "ready": {
                    "type": "boolean"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ProjectPlanLaunchItem"
                    }
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "appMap": {
            "anyOf": [
              {
                "type": "object",
                "required": [
                  "codeVersion",
                  "mappedAt",
                  "screens",
                  "endpoints",
                  "storage"
                ],
                "description": "Where things live in the code. Each list holds at most 25 items; count is the full number.",
                "properties": {
                  "codeVersion": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "mappedAt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "screens": {
                    "type": "object",
                    "required": [
                      "count",
                      "items"
                    ],
                    "properties": {
                      "count": {
                        "type": "integer"
                      },
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "name",
                            "anchor",
                            "path"
                          ],
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "anchor": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "File and line in the code, for example server/routes.js:42, or the file alone."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "path": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          }
                        }
                      }
                    }
                  },
                  "endpoints": {
                    "type": "object",
                    "required": [
                      "count",
                      "items"
                    ],
                    "properties": {
                      "count": {
                        "type": "integer"
                      },
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "name",
                            "anchor",
                            "writes"
                          ],
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "anchor": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "File and line in the code, for example server/routes.js:42, or the file alone."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "writes": {
                              "type": "boolean",
                              "description": "The route changes stored data."
                            }
                          }
                        }
                      }
                    }
                  },
                  "storage": {
                    "type": "object",
                    "required": [
                      "count",
                      "items"
                    ],
                    "properties": {
                      "count": {
                        "type": "integer"
                      },
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "name",
                            "anchor",
                            "kind",
                            "where"
                          ],
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "anchor": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "File and line in the code, for example server/routes.js:42, or the file alone."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "kind": {
                              "type": "string"
                            },
                            "where": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "lastRun": {
            "anyOf": [
              {
                "type": "object",
                "required": [
                  "runId",
                  "kind",
                  "endedAt",
                  "codeVersion",
                  "filesChanged",
                  "appMap"
                ],
                "description": "The last run that changed the code.",
                "properties": {
                  "runId": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "description": "chat (an ask) or sprint (a build of planned work)."
                  },
                  "endedAt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "codeVersion": {
                    "type": "object",
                    "required": [
                      "before",
                      "after"
                    ],
                    "properties": {
                      "before": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "after": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    }
                  },
                  "filesChanged": {
                    "type": "object",
                    "required": [
                      "count",
                      "paths"
                    ],
                    "properties": {
                      "count": {
                        "type": "integer"
                      },
                      "paths": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "appMap": {
                    "anyOf": [
                      {
                        "type": "object",
                        "required": [
                          "added",
                          "removed",
                          "changed"
                        ],
                        "properties": {
                          "added": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "kind",
                                "name"
                              ],
                              "properties": {
                                "kind": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                }
                              }
                            }
                          },
                          "removed": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "kind",
                                "name"
                              ],
                              "properties": {
                                "kind": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                }
                              }
                            }
                          },
                          "changed": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "kind",
                                "name"
                              ],
                              "properties": {
                                "kind": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "GetPlanResponse": {
        "type": "object",
        "required": [
          "projectId",
          "specId",
          "plan",
          "markdown"
        ],
        "properties": {
          "projectId": {
            "type": "string",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "specId": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[a-fA-F0-9]{24}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "plan": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProjectPlan"
              },
              {
                "type": "null"
              }
            ]
          },
          "markdown": {
            "type": "string",
            "description": "The plan as Markdown for a coding agent."
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Specifications"
    },
    {
      "name": "Browser Agents"
    },
    {
      "name": "Account"
    }
  ]
}
