{
  "openapi": "3.1.0",
  "info": {
    "title": "ChatStack Agent API",
    "version": "1.0.0",
    "description": "Authenticated REST API for autonomous AI agents to submit structured Product Requirements Documents (PRDs) to the ChatStack platform. Agents construct their own PRD artifacts and submit them directly — no interactive interview required.\n\nThe ChatStack interview experience at https://www.chatstack.app/ remains the recommended path for human users. This API is designed for AI agents that can independently generate the required JSON artifacts.\n\nOnce submitted, a project is created in the ChatStack portal (https://portal.chatstack.app) and the ChatStack team will review your submission.",
    "contact": {
      "name": "ChatStack",
      "url": "https://www.chatstack.app/speak-to-a-human"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://www.chatstack.app",
      "description": "Production"
    }
  ],
  "security": [
    {
      "AgentApiKey": []
    }
  ],
  "paths": {
    "/api/agent/submit": {
      "post": {
        "operationId": "submitPrd",
        "summary": "Submit a structured PRD",
        "description": "Submit a complete set of PRD artifacts to ChatStack. The payload must include approved user stories and functional requirements at minimum. Technical specifications and cost estimates are optional but strongly recommended for the best review experience.\n\nThe response includes the submission ID and, if an email was provided, the created project and version IDs that can be viewed in the ChatStack portal.",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitRequest"
              },
              "example": {
                "artifacts": {
                  "stories_json_approved": {
                    "stories": [
                      {
                        "id": "US-1",
                        "user_type": "admin",
                        "user_story": "As an admin, I want to invite team members by email so that I can manage access to the workspace.",
                        "acceptance_criteria": [
                          "Admin can enter one or more email addresses",
                          "Invitee receives an email with a signup link",
                          "Invitee is assigned the 'member' role by default"
                        ],
                        "nfr": ["Invitation email delivered within 60 seconds"],
                        "notes": "",
                        "mvp": true
                      }
                    ],
                    "global_nfr": ["App must be responsive on mobile and desktop"]
                  },
                  "requirements_json_approved": {
                    "requirements": [
                      {
                        "id": "FR-1",
                        "category": "functional",
                        "description": "The system must allow admins to invite users via email.",
                        "priority": "must-have",
                        "linked_stories": ["US-1"]
                      }
                    ]
                  },
                  "techspec_json_approved": {
                    "specifications": [
                      {
                        "id": "TS-1",
                        "area": "Authentication",
                        "description": "Use Supabase Auth with magic-link email for passwordless sign-in.",
                        "linked_requirements": ["FR-1"]
                      }
                    ]
                  },
                  "estimate_json": {
                    "meta": {
                      "currency": "USD",
                      "rate_per_point": 120,
                      "ai_efficiency_discount": 0.65
                    },
                    "rows": [
                      {
                        "id": "US-1",
                        "title": "Admin invites team members",
                        "story_points": 3,
                        "hours": 6,
                        "cost_before_discount": 720,
                        "cost_after_discount": 252
                      }
                    ],
                    "totals": {
                      "story_points": 3,
                      "hours": 6,
                      "cost_before_discount": 720,
                      "cost_after_discount": 252
                    }
                  }
                },
                "interview_summary": "A SaaS workspace app for small teams. Core features: user invitations, project boards, real-time collaboration, and Slack notifications.",
                "first_name": "My",
                "last_name": "Agent",
                "email": "builder@example.com",
                "country": "US"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "PRD submitted successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmitSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation error — the request body failed schema validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Payload exceeds the 10 MB limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Maximum 5 submissions per hour per IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "AgentApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key issued by ChatStack for autonomous agent access. Contact the ChatStack team to request a key."
      }
    },
    "schemas": {
      "SubmitRequest": {
        "type": "object",
        "required": ["artifacts", "interview_summary"],
        "properties": {
          "artifacts": {
            "$ref": "#/components/schemas/Artifacts"
          },
          "interview_summary": {
            "type": "string",
            "description": "A plain-text narrative describing the project. This is shown to the ChatStack reviewer and used as context for the portal. Aim for 2–5 sentences covering the problem, target users, and key goals.",
            "minLength": 20
          },
          "first_name": {
            "type": "string",
            "description": "First name of the person or organisation on whose behalf the agent is submitting."
          },
          "last_name": {
            "type": "string",
            "description": "Last name of the person or organisation on whose behalf the agent is submitting."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address used to create or match a portal account. If omitted, the submission is stored as anonymous and no portal project is created."
          },
          "country": {
            "type": "string",
            "description": "Country of the submitter (ISO 3166-1 alpha-2 code or full country name)."
          },
          "message": {
            "type": "string",
            "description": "Optional free-text note to the ChatStack team."
          }
        }
      },
      "Artifacts": {
        "type": "object",
        "required": ["stories_json_approved", "requirements_json_approved"],
        "description": "The four structured PRD artifacts. stories_json_approved and requirements_json_approved are required. techspec_json_approved and estimate_json are strongly recommended.",
        "properties": {
          "stories_json_approved": {
            "$ref": "#/components/schemas/StoriesDocument"
          },
          "requirements_json_approved": {
            "$ref": "#/components/schemas/RequirementsDocument"
          },
          "techspec_json_approved": {
            "$ref": "#/components/schemas/TechSpecDocument"
          },
          "estimate_json": {
            "$ref": "#/components/schemas/EstimateDocument"
          }
        }
      },
      "StoriesDocument": {
        "type": "object",
        "required": ["stories"],
        "description": "User stories following the 'As a <user_type>, I want <goal> so that <benefit>' format.",
        "properties": {
          "stories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserStory"
            }
          },
          "global_nfr": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Non-functional requirements that apply to the entire system.",
            "default": []
          }
        }
      },
      "UserStory": {
        "type": "object",
        "required": ["id", "user_type", "user_story", "acceptance_criteria", "mvp"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier in the format US-<n> (e.g. US-1, US-2).",
            "pattern": "^US-\\d+$"
          },
          "user_type": {
            "type": "string",
            "description": "The role or persona of the user (e.g. 'admin', 'guest', 'customer')."
          },
          "user_story": {
            "type": "string",
            "description": "Full user story in the canonical format: 'As a <user_type>, I want <goal> so that <benefit>.'"
          },
          "acceptance_criteria": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "2–5 testable conditions that define when this story is complete.",
            "minItems": 1
          },
          "nfr": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Non-functional requirements specific to this story. Empty array if none.",
            "default": []
          },
          "notes": {
            "type": "string",
            "description": "Optional clarifying notes. Empty string if none.",
            "default": ""
          },
          "mvp": {
            "type": "boolean",
            "description": "Whether this story is in the Minimum Viable Product scope.",
            "default": true
          }
        }
      },
      "RequirementsDocument": {
        "type": "object",
        "required": ["requirements"],
        "properties": {
          "requirements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Requirement"
            }
          }
        }
      },
      "Requirement": {
        "type": "object",
        "required": ["id", "category", "description"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier (e.g. FR-1, NFR-1, ASS-1)."
          },
          "category": {
            "type": "string",
            "enum": ["functional", "non-functional", "assumption"],
            "description": "Classification of the requirement."
          },
          "description": {
            "type": "string"
          },
          "priority": {
            "type": "string",
            "enum": ["must-have", "should-have", "could-have", "won't-have"],
            "description": "MoSCoW priority."
          },
          "linked_stories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IDs of user stories this requirement traces to (e.g. ['US-1']).",
            "default": []
          }
        }
      },
      "TechSpecDocument": {
        "type": "object",
        "required": ["specifications"],
        "properties": {
          "specifications": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TechSpec"
            }
          }
        }
      },
      "TechSpec": {
        "type": "object",
        "required": ["id", "area", "description"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier (e.g. TS-1)."
          },
          "area": {
            "type": "string",
            "description": "Architectural area (e.g. 'Authentication', 'Database', 'Frontend', 'API', 'Infrastructure')."
          },
          "description": {
            "type": "string",
            "description": "Technical decision or constraint for this area."
          },
          "linked_requirements": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IDs of requirements this spec addresses.",
            "default": []
          }
        }
      },
      "EstimateDocument": {
        "type": "object",
        "required": ["meta", "rows", "totals"],
        "description": "Story-point-based cost estimate applying ChatStack's AI efficiency model.",
        "properties": {
          "meta": {
            "type": "object",
            "description": "Estimation parameters.",
            "properties": {
              "currency": {
                "type": "string",
                "description": "ISO 4217 currency code (e.g. 'USD', 'ZAR').",
                "default": "USD"
              },
              "rate_per_point": {
                "type": "number",
                "description": "Cost in currency units per story point before AI discount."
              },
              "ai_efficiency_discount": {
                "type": "number",
                "description": "Fractional AI efficiency discount (e.g. 0.65 = 65% reduction).",
                "minimum": 0,
                "maximum": 1
              }
            }
          },
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EstimateRow"
            }
          },
          "totals": {
            "type": "object",
            "description": "Aggregated totals across all rows.",
            "properties": {
              "story_points": { "type": "number" },
              "hours": { "type": "number" },
              "cost_before_discount": { "type": "number" },
              "cost_after_discount": { "type": "number" }
            }
          },
          "assumptions": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Assumptions underpinning the estimate.",
            "default": []
          },
          "risks": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Risks that could affect the estimate.",
            "default": []
          }
        }
      },
      "EstimateRow": {
        "type": "object",
        "required": ["id", "title", "story_points", "hours"],
        "properties": {
          "id": {
            "type": "string",
            "description": "References a user story ID (e.g. 'US-1')."
          },
          "title": {
            "type": "string"
          },
          "story_points": {
            "type": "number",
            "minimum": 0
          },
          "hours": {
            "type": "number",
            "minimum": 0
          },
          "cost_before_discount": {
            "type": "number",
            "minimum": 0
          },
          "cost_after_discount": {
            "type": "number",
            "minimum": 0
          }
        }
      },
      "SubmitSuccess": {
        "type": "object",
        "required": ["ok", "id"],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [true]
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Submission record ID."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Created project ID in the ChatStack portal. Present only when an email was provided and matched or created a portal account."
          },
          "version_id": {
            "type": "string",
            "format": "uuid",
            "description": "Created project version ID. Present alongside project_id."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Non-fatal warnings about artifact parsing. The submission was accepted but some artifacts may have needed repair."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error description."
          },
          "details": {
            "description": "Additional validation details — present on 400 errors.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "path": { "type": "string" },
                    "message": { "type": "string" }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
}
