{
  "openapi": "3.1.0",
  "info": {
    "title": "FullSkill API",
    "description": "Build production-quality AI agent skills programmatically. Submit a skill specification, monitor the 44-step build pipeline, and download the finished skill.",
    "version": "1.0.0",
    "contact": {
      "name": "FullSkill Support",
      "email": "support@fullskill.ai",
      "url": "https://fullskill.ai/docs/api"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://fullskill.ai/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Builds",
      "description": "Create and monitor skill builds"
    },
    {
      "name": "Catalog",
      "description": "Browse and install published skills"
    },
    {
      "name": "Keys",
      "description": "Manage API keys (session auth only)"
    }
  ],
  "paths": {
    "/builds": {
      "post": {
        "operationId": "createBuild",
        "tags": ["Builds"],
        "summary": "Build a skill",
        "description": "Submit a skill specification and start the 44-step build pipeline. Deducts 1 credit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuildCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Build started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildCreatedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing required fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "No credits available",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listBuilds",
        "tags": ["Builds"],
        "summary": "List builds",
        "description": "List all builds for the authenticated user.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by build status",
            "schema": {
              "type": "string",
              "enum": ["discovery", "building", "review", "complete", "error"]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page (default: 20, max: 100)",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of builds",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "builds": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BuildSummary"
                      }
                    }
                  },
                  "required": ["builds"]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/builds/{id}": {
      "get": {
        "operationId": "getBuild",
        "tags": ["Builds"],
        "summary": "Check build status",
        "description": "Get detailed status for a build, including step breakdown and completion percentage.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Build UUID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Build status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildDetailResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/builds/{id}/files": {
      "get": {
        "operationId": "getBuildFiles",
        "tags": ["Builds"],
        "summary": "Get build files",
        "description": "Retrieve all generated skill files as JSON. Available when build status is 'complete' or 'review'.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Build UUID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Generated files",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildFilesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Build is not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/builds/{id}/download": {
      "get": {
        "operationId": "downloadBuild",
        "tags": ["Builds"],
        "summary": "Download build as ZIP",
        "description": "Download all generated skill files as a ZIP archive. Available when build status is 'complete' or 'review'.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Build UUID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ZIP archive",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Build is not ready for download",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/builds/{id}/events": {
      "get": {
        "operationId": "streamBuildEvents",
        "tags": ["Builds"],
        "summary": "Stream build events (SSE)",
        "description": "Subscribe to real-time build progress via Server-Sent Events. The stream emits events as each step starts, progresses, and completes. The connection closes when the build finishes or errors.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Build UUID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SSE event stream",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Server-Sent Events stream. Each event is a JSON object with type, phase, step, and message fields."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/catalog": {
      "get": {
        "operationId": "browseCatalog",
        "tags": ["Catalog"],
        "summary": "Browse skill catalog",
        "description": "Browse the public skill catalog. No authentication required.",
        "security": [],
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "description": "Filter by category",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Full-text search across name, description, and tags",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page (default: 20, max: 100)",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Pagination offset",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skill catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogResponse"
                }
              }
            }
          }
        }
      }
    },
    "/catalog/{slug}": {
      "get": {
        "operationId": "getSkillDetails",
        "tags": ["Catalog"],
        "summary": "Get skill details",
        "description": "Get full details for a specific published skill, including a preview of the SKILL.md content.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug (URL-safe name)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skill details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillDetailResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/catalog/{slug}/install": {
      "get": {
        "operationId": "installSkill",
        "tags": ["Catalog"],
        "summary": "Install skill (download ZIP)",
        "description": "Download a published skill as a ZIP archive for direct installation into your AI agent.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug (URL-safe name)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ZIP archive of the skill",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/keys": {
      "post": {
        "operationId": "createKey",
        "tags": ["Keys"],
        "summary": "Create API key",
        "description": "Create a new API key. Requires browser session authentication (API keys cannot create other keys).",
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Friendly name for the key (max 100 chars)",
                    "default": "Default",
                    "maxLength": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created. The full key is only shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyCreatedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Session authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listKeys",
        "tags": ["Keys"],
        "summary": "List API keys",
        "description": "List all API keys for the authenticated user. Requires browser session authentication.",
        "security": [],
        "responses": {
          "200": {
            "description": "List of API keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KeySummary"
                      }
                    }
                  },
                  "required": ["keys"]
                }
              }
            }
          },
          "401": {
            "description": "Session authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "revokeKey",
        "tags": ["Keys"],
        "summary": "Revoke API key",
        "description": "Revoke an API key. Requires browser session authentication.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key_id": {
                    "type": "string",
                    "description": "ID of the key to revoke"
                  }
                },
                "required": ["key_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": ["success"]
                }
              }
            }
          },
          "400": {
            "description": "Missing key_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Session authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Key not found or already revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key starting with fs_live_. Obtain from https://fullskill.ai/dashboard/api-keys"
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Authentication required or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Invalid or revoked API key"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Build not found"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message"
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code (optional)"
          }
        },
        "required": ["error"]
      },
      "BuildCreateRequest": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "What the skill does (2-3 sentences)"
          },
          "problem": {
            "type": "string",
            "description": "What problem the skill solves"
          },
          "audience": {
            "type": "string",
            "description": "Target audience for the skill"
          },
          "use_cases": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "3+ specific scenarios where the skill would be activated"
          },
          "quality": {
            "type": "string",
            "enum": ["personal", "team", "marketplace"],
            "default": "marketplace",
            "description": "Quality target for the build"
          },
          "reference_materials": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional domain references, examples, or notes"
          },
          "output_examples": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional examples of ideal output"
          }
        },
        "required": ["description", "problem", "audience", "use_cases"]
      },
      "BuildCreatedResponse": {
        "type": "object",
        "properties": {
          "build_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": ["building"]
          },
          "current_phase": {
            "type": "integer"
          },
          "current_step": {
            "type": "integer"
          },
          "poll_url": {
            "type": "string",
            "description": "URL to poll for build status"
          },
          "events_url": {
            "type": "string",
            "description": "URL for SSE event stream"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["build_id", "status", "current_phase", "current_step", "poll_url", "events_url", "created_at"]
      },
      "BuildSummary": {
        "type": "object",
        "properties": {
          "build_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/BuildStatus"
          },
          "current_phase": {
            "type": "integer"
          },
          "current_step": {
            "type": "integer"
          },
          "skill_name": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["build_id", "status", "current_phase", "current_step", "created_at", "updated_at"]
      },
      "BuildDetailResponse": {
        "type": "object",
        "properties": {
          "build_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/BuildStatus"
          },
          "current_phase": {
            "type": "integer"
          },
          "current_step": {
            "type": "integer"
          },
          "skill_name": {
            "type": ["string", "null"]
          },
          "completion_pct": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Percentage of steps completed"
          },
          "steps": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "completed": {
                "type": "integer"
              },
              "running": {
                "type": "integer"
              },
              "pending": {
                "type": "integer"
              },
              "errored": {
                "type": "integer",
                "description": "Only present if > 0"
              }
            },
            "required": ["total", "completed", "running", "pending"]
          },
          "file_count": {
            "type": "integer",
            "description": "Number of generated files so far"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["build_id", "status", "current_phase", "current_step", "completion_pct", "steps", "file_count", "created_at", "updated_at"]
      },
      "BuildFilesResponse": {
        "type": "object",
        "properties": {
          "build_id": {
            "type": "string",
            "format": "uuid"
          },
          "skill_name": {
            "type": ["string", "null"]
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string",
                  "description": "Relative file path (e.g., SKILL.md, references/topic.md)"
                },
                "content": {
                  "type": "string",
                  "description": "Full file content"
                },
                "line_count": {
                  "type": "integer"
                }
              },
              "required": ["path", "content", "line_count"]
            }
          }
        },
        "required": ["build_id", "files"]
      },
      "BuildStatus": {
        "type": "string",
        "enum": ["discovery", "building", "review", "complete", "error"],
        "description": "Build lifecycle status"
      },
      "SSEEvent": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["step_start", "step_progress", "step_complete", "phase_complete", "file_generated", "review_checkpoint", "build_complete", "build_error"],
            "description": "Event type"
          },
          "phase": {
            "type": "integer",
            "description": "Phase number (1-7)"
          },
          "step": {
            "type": "integer",
            "description": "Step number within the phase"
          },
          "message": {
            "type": "string",
            "description": "Human-readable progress message"
          },
          "data": {
            "type": "object",
            "description": "Additional event-specific data"
          }
        },
        "required": ["type"]
      },
      "CatalogResponse": {
        "type": "object",
        "properties": {
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogEntry"
            }
          },
          "total": {
            "type": "integer",
            "description": "Total number of matching skills"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        },
        "required": ["skills", "total", "limit", "offset"]
      },
      "CatalogEntry": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "file_count": {
            "type": "integer"
          },
          "line_count": {
            "type": "integer"
          },
          "download_count": {
            "type": "integer"
          },
          "price_cents": {
            "type": "integer",
            "description": "Price in cents (0 = free)"
          }
        },
        "required": ["slug", "name", "description", "category", "tags", "file_count", "line_count", "download_count", "price_cents"]
      },
      "SkillDetailResponse": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skill_md_preview": {
            "type": ["string", "null"],
            "description": "Preview of the SKILL.md content (first 50 lines)"
          },
          "file_count": {
            "type": "integer"
          },
          "line_count": {
            "type": "integer"
          },
          "download_count": {
            "type": "integer"
          },
          "price_cents": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["slug", "name", "description", "category", "tags", "file_count", "line_count", "download_count", "price_cents", "created_at"]
      },
      "KeyCreatedResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Key identifier"
          },
          "name": {
            "type": "string",
            "description": "Friendly name"
          },
          "key": {
            "type": "string",
            "description": "Full API key (shown only once). Starts with fs_live_"
          },
          "prefix": {
            "type": "string",
            "description": "First 16 characters of the key for identification"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "name", "key", "prefix", "created_at"]
      },
      "KeySummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "First 16 characters of the key"
          },
          "last_used_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "is_active": {
            "type": "boolean"
          }
        },
        "required": ["id", "name", "prefix", "created_at", "is_active"]
      }
    }
  }
}
