{
  "openapi": "3.1.0",
  "info": {
    "title": "Founder Studio Agent API",
    "version": "1.1.0",
    "summary": "Self-serve video script generation for autonomous agents.",
    "description": "Discovery, instant API keys, per-job pricing and programmatic download. Script generation is live and billable. The demo, presentation and video job types are listed and priced but the rendering backend is not attached yet — they return the script stage only. Check capabilities[].status in /api/agents/discover before spending.",
    "contact": { "name": "Strategic Innovations", "url": "https://teleprompter.strategic-innovations.ai/agents" },
    "license": { "name": "Proprietary" }
  },
  "servers": [{ "url": "https://teleprompter.strategic-innovations.ai" }],
  "security": [{ "agentKey": [] }],
  "tags": [
    { "name": "discovery", "description": "Unauthenticated endpoints an agent reads before committing." },
    { "name": "jobs", "description": "Submit, inspect, purchase and download work." }
  ],
  "paths": {
    "/api/agents/discover": {
      "get": {
        "tags": ["discovery"],
        "summary": "Capabilities, pricing, auth and workflow",
        "description": "The machine-readable contract. Every capability carries a status of available or unavailable, and prices are computed from the same function that bills the job.",
        "security": [],
        "responses": {
          "200": {
            "description": "The capability catalogue.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Discovery" } } }
          }
        }
      }
    },
    "/api/agents/pricing": {
      "get": {
        "tags": ["discovery"],
        "summary": "Priced tiers per type and duration",
        "security": [],
        "responses": {
          "200": {
            "description": "Credit and cent quotes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "centsPerCredit": { "type": "integer", "examples": [25] },
                    "tiers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": { "$ref": "#/components/schemas/JobType" },
                          "seconds": { "type": "integer" },
                          "credits": { "type": "integer" },
                          "cents": { "type": "integer" }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/signup": {
      "post": {
        "tags": ["discovery"],
        "summary": "Create an agent account and receive an API key",
        "description": "Issued immediately with no human approval. The key is returned once; there is no recovery endpoint.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "agentName": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Sanitised to letters, digits, dash and underscore. Defaults to a generated name if omitted.",
                    "examples": ["my-agent"]
                  },
                  "email": { "type": "string", "format": "email", "description": "Optional contact address." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An account and its key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "agentId": { "type": "string", "examples": ["agt_302330a04f77cdd07576d41e"] },
                    "apiKey": { "type": "string", "pattern": "^fsk_[a-f0-9]{32}$" },
                    "plan": { "type": "string", "examples": ["free"] },
                    "agentName": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/api/agents/jobs": {
      "post": {
        "tags": ["jobs"],
        "summary": "Submit a brief and generate a job",
        "description": "Generation is synchronous: the request blocks until the script exists, typically around 30 seconds. There is no queue and nothing to poll. The job is priced at submission and is not charged until purchased.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["brief"],
                "properties": {
                  "brief": {
                    "type": "string",
                    "minLength": 1,
                    "description": "What the video should say. Whitespace is collapsed and the value is trimmed to 2000 characters.",
                    "examples": ["A 60 second intro to Founder Studio for solo founders"]
                  },
                  "options": {
                    "type": "object",
                    "properties": {
                      "type": { "$ref": "#/components/schemas/JobType" },
                      "seconds": {
                        "type": "integer",
                        "minimum": 15,
                        "maximum": 300,
                        "default": 60,
                        "description": "Clamped to 15–300. The clamped value is what you are billed for."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generated job. Inspect status: script_ready means it can be purchased, error means generation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "ok": { "type": "boolean" }, "job": { "$ref": "#/components/schemas/Job" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      },
      "get": {
        "tags": ["jobs"],
        "summary": "List your 50 most recent jobs",
        "responses": {
          "200": {
            "description": "Jobs, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "jobs": { "type": "array", "items": { "$ref": "#/components/schemas/Job" } }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/api/agents/jobs/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/JobId" }],
      "get": {
        "tags": ["jobs"],
        "summary": "Fetch one job",
        "responses": {
          "200": {
            "description": "The job.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "ok": { "type": "boolean" }, "job": { "$ref": "#/components/schemas/Job" } }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/api/agents/jobs/{id}/purchase": {
      "parameters": [{ "$ref": "#/components/parameters/JobId" }],
      "post": {
        "tags": ["jobs"],
        "summary": "Pay for a job to unlock its download",
        "description": "The job must be in status script_ready or complete. Note that already_paid and job_not_ready are returned as HTTP 200 with ok:false — branch on ok, not on the status code.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["paymentMethod"],
                "properties": { "paymentMethod": { "type": "string", "enum": ["stripe", "crypto"] } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated job, plus a checkoutUrl for stripe or a paymentAddress for crypto. May instead carry ok:false with already_paid or job_not_ready.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "job": { "$ref": "#/components/schemas/Job" },
                    "checkoutUrl": { "type": "string" },
                    "paymentAddress": { "type": "string" },
                    "amount": { "type": "number" },
                    "currency": { "type": "string", "examples": ["USDC"] },
                    "error": { "type": "string", "enum": ["already_paid", "job_not_ready"] }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/api/agents/jobs/{id}/download": {
      "parameters": [{ "$ref": "#/components/parameters/JobId" }],
      "get": {
        "tags": ["jobs"],
        "summary": "Download the artifact",
        "description": "Returns the artifact named in capabilities[].delivers for the job's type. Today every job type delivers UTF-8 text as an attachment named video-script.txt.",
        "responses": {
          "200": {
            "description": "The artifact as a file attachment.",
            "content": { "text/plain": { "schema": { "type": "string" } } },
            "headers": {
              "content-disposition": {
                "schema": { "type": "string", "examples": ["attachment; filename=\"video-script.txt\""] }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": {
            "description": "The job has not been purchased.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "agentKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "The key returned by POST /api/agents/signup. Format: fsk_ followed by 32 lowercase hex characters. Not a bearer token."
      }
    },
    "parameters": {
      "JobId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "examples": ["job_3159d74ab79e97d81307e63d"] }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request was malformed.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Unauthorized": {
        "description": "Missing, malformed or unknown x-api-key.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "No such job, or the job belongs to another agent.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Unavailable": {
        "description": "Storage is unavailable. Retry.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "JobType": {
        "type": "string",
        "enum": ["script", "demo", "presentation", "video"],
        "default": "script",
        "description": "Only script is currently fulfilled. The others accept briefs, are priced, and return the script stage only."
      },
      "Job": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "script_ready", "paid", "complete", "error"] },
          "brief": { "type": "string" },
          "priceCents": { "type": "integer" },
          "paid": { "type": "boolean" },
          "paymentMethod": { "type": ["string", "null"], "enum": ["stripe", "crypto", null] },
          "downloadUrl": { "type": ["string", "null"] },
          "script": { "type": ["string", "null"] },
          "error": { "type": ["string", "null"] },
          "createdAt": { "type": "integer", "description": "Unix epoch milliseconds." },
          "completedAt": { "type": ["integer", "null"] }
        }
      },
      "Discovery": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "version": { "type": "string" },
          "description": { "type": "string" },
          "docsUrl": { "type": "string", "format": "uri" },
          "capabilities": { "type": "array", "items": { "$ref": "#/components/schemas/Capability" } },
          "pricing": { "type": "object" },
          "auth": { "type": "object" },
          "workflow": { "type": "array", "items": { "type": "object" } },
          "endpoints": { "type": "array", "items": { "type": "object" } },
          "unsupported": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Surfaces this API deliberately does not provide."
          }
        }
      },
      "Capability": {
        "type": "object",
        "properties": {
          "type": { "$ref": "#/components/schemas/JobType" },
          "label": { "type": "string" },
          "description": { "type": "string" },
          "status": {
            "type": "string",
            "enum": ["available", "unavailable"],
            "description": "available means the capability delivers what it describes. unavailable means it does not — check unavailableReason."
          },
          "unavailableReason": { "type": "string" },
          "delivers": {
            "type": "object",
            "properties": {
              "contentType": { "type": "string" },
              "artifact": { "type": "string" },
              "filename": { "type": "string" }
            }
          },
          "pricePerJobCents": { "type": "integer" },
          "priceBasis": {
            "type": "object",
            "properties": {
              "seconds": { "type": "integer" },
              "credits": { "type": "integer" },
              "centsPerCredit": { "type": "integer" }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": { "ok": { "type": "boolean", "const": false }, "error": { "type": "string" } }
      }
    }
  }
}
