{
  "openapi": "3.1.0",
  "info": {
    "title": "AskEditor Platform API",
    "version": "1.0.0-preview",
    "description": "The video editing API for AI agents. Every response is wrapped as { success, data }. Templates are addressed by id; synchronous templates return their result in the run call, queued templates resolve through the jobs envelope."
  },
  "servers": [
    {
      "url": "https://api.askeditor.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/recipes": {
      "get": {
        "summary": "List templates (the menu)",
        "operationId": "listTemplates",
        "responses": {
          "200": {
            "description": "The live template catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Template"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/estimate": {
      "get": {
        "summary": "Estimate a run (free)",
        "operationId": "estimate",
        "parameters": [
          {
            "name": "recipeId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "message-bubbles",
                "remove-background",
                "tighten",
                "launch-cut",
                "tracked-title-card",
                "text-behind"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Price, ETA, and typed blockers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Estimate"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/uploads": {
      "post": {
        "summary": "Mint an upload ticket",
        "operationId": "createUpload",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "purpose": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A one-time upload ticket. Browser users open uploadUrl; shells POST the file directly (next endpoint).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ticket": {
                          "type": "string"
                        },
                        "uploadUrl": {
                          "type": "string"
                        },
                        "expiresInSec": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/uploads/{ticket}/file": {
      "post": {
        "summary": "Fill a ticket from a shell (no browser)",
        "operationId": "uploadFile",
        "security": [],
        "description": "The ticket IS the credential: one file, one project, once, within 30 minutes. No API key here on purpose — never put a spending credential in a shell command.",
        "parameters": [
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The material handle to pass to a run.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "material": {
                          "type": "string"
                        },
                        "bytes": {
                          "type": "number"
                        },
                        "status": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/uploads/{ticket}": {
      "get": {
        "summary": "Poll a ticket",
        "operationId": "getUpload",
        "parameters": [
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ticket state; material is set once uploaded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "uploaded",
                            "expired"
                          ]
                        },
                        "material": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/run/remove-background": {
      "post": {
        "summary": "Run: Remove Background (synchronous)",
        "description": "Cut the subject out of a video: the person isolated on a true alpha channel, ready to composite anywhere. SYNCHRONOUS: the call returns the finished cutout (~40-90s), no polling. The reflex call when an agent needs a background gone.",
        "operationId": "run_remove_background",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "material": {
                    "type": "string",
                    "description": "A public https url, or an upload-ticket material handle."
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "best",
                      "fast"
                    ],
                    "description": "'best' (default) is the quality pick. 'fast' trades a little edge fidelity for speed."
                  },
                  "outputFormat": {
                    "type": "string",
                    "enum": [
                      "webm",
                      "mov",
                      "mp4"
                    ],
                    "description": "'webm' (default) = VP9 with true alpha. 'mov' = ProRes 4444 alpha. 'mp4' = green screen."
                  }
                },
                "required": [
                  "material"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The finished result — no polling. Typed refusals come back as 4xx with { errorCode }.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/SyncRunResult"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs": {
      "get": {
        "summary": "List recent jobs",
        "operationId": "listJobs",
        "responses": {
          "200": {
            "description": "Recent jobs for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{envelopeId}": {
      "get": {
        "summary": "Get a job envelope (queued templates)",
        "operationId": "getJob",
        "parameters": [
          {
            "name": "envelopeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job state; completed jobs carry finalUrl + canvasUrl.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Job"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "summary": "Account, credits, and this key's scopes",
        "operationId": "me",
        "responses": {
          "200": {
            "description": "Who am I and what can I afford.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "projectName": {
                          "type": "string"
                        },
                        "plan": {
                          "type": "string"
                        },
                        "creditsRemaining": {
                          "type": "number"
                        },
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "schemas": {
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "priceCredits": {
            "type": "number"
          },
          "etaSeconds": {
            "type": "number"
          },
          "hasReviewGate": {
            "type": "boolean"
          }
        }
      },
      "Estimate": {
        "type": "object",
        "properties": {
          "recipeId": {
            "type": "string"
          },
          "credits": {
            "type": "number"
          },
          "etaSeconds": {
            "type": "number"
          },
          "creditsRemaining": {
            "type": "number"
          },
          "watermarked": {
            "type": "boolean"
          },
          "blockers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "INSUFFICIENT_CREDITS",
                    "IN_FLIGHT",
                    "SCOPE_DENIED",
                    "RECIPE_NOT_ALLOWED",
                    "SPEND_CAP_REACHED"
                  ]
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "SyncRunResult": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "completed"
            ]
          },
          "processedVideoUrl": {
            "type": "string",
            "description": "The finished output (e.g. VP9 alpha webm)."
          },
          "canvasId": {
            "type": "string"
          },
          "editorPath": {
            "type": "string",
            "description": "Open the same result as an editable timeline."
          },
          "credits": {
            "type": "number"
          },
          "creditsCharged": {
            "type": "boolean"
          },
          "cached": {
            "type": "boolean",
            "description": "true when an identical prior run was returned free."
          }
        }
      },
      "Job": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "finalUrl": {
            "type": "string"
          },
          "canvasId": {
            "type": "string"
          },
          "canvasUrl": {
            "type": "string"
          }
        }
      }
    }
  }
}
