{
  "openapi": "3.1.0",
  "info": {
    "title": "InspectionVoice Public API",
    "version": "1.0.0",
    "description": "Programmatic access to InspectionVoice projects, inspections, observations, reports, webhooks, and analytics. All endpoints require a bearer API key with the appropriate scope.",
    "contact": {
      "name": "InspectionVoice developers",
      "url": "https://inspectionvoice.com/developers"
    }
  },
  "servers": [{ "url": "https://inspectionvoice.com/api/v1" }],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key in the form `Bearer iv_sk_...`. Keys are issued under Admin Settings → API keys."
      }
    },
    "schemas": {
      "Project": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "address": { "type": "string", "nullable": true },
          "city": { "type": "string", "nullable": true },
          "state": { "type": "string", "nullable": true },
          "zip": { "type": "string", "nullable": true },
          "status": { "type": "string" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "Inspection": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "project_id": { "type": "string", "format": "uuid" },
          "inspector_id": { "type": "string", "format": "uuid" },
          "status": { "type": "string" },
          "scheduled_at": { "type": "string", "format": "date-time", "nullable": true },
          "started_at": { "type": "string", "format": "date-time", "nullable": true },
          "completed_at": { "type": "string", "format": "date-time", "nullable": true },
          "sent_at": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "Observation": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "inspection_id": { "type": "string", "format": "uuid" },
          "description": { "type": "string" },
          "corrective_action": { "type": "string", "nullable": true },
          "severity": {
            "type": "string",
            "enum": ["critical", "major", "minor", "info"],
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": ["pass", "fail", "partial", "not_applicable", "pending"]
          },
          "location": { "type": "string", "nullable": true }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "target_url": { "type": "string", "format": "uri" },
          "events": { "type": "array", "items": { "type": "string" } },
          "is_active": { "type": "boolean" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "code": { "type": "string" }
        },
        "required": ["error"]
      }
    }
  },
  "security": [{ "bearer": [] }],
  "paths": {
    "/projects": {
      "get": {
        "summary": "List projects",
        "description": "List projects for the caller's organization.",
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1, "default": 1 } },
          { "name": "per_page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 } }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/Project" } },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "page": { "type": "integer" },
                        "per_page": { "type": "integer" },
                        "total": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" },
          "429": { "description": "Rate limit exceeded" }
        }
      },
      "post": {
        "summary": "Create project",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": { "type": "string" },
                  "address": { "type": "string" },
                  "city": { "type": "string" },
                  "state": { "type": "string" },
                  "zip": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } }
          }
        }
      }
    },
    "/projects/{id}": {
      "parameters": [
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
      ],
      "get": { "summary": "Get project", "responses": { "200": { "description": "ok" }, "404": { "description": "not found" } } },
      "patch": { "summary": "Update project", "responses": { "200": { "description": "ok" } } },
      "delete": { "summary": "Archive project", "responses": { "200": { "description": "archived" } } }
    },
    "/inspections": {
      "get": {
        "summary": "List inspections",
        "parameters": [
          { "name": "project_id", "in": "query", "schema": { "type": "string", "format": "uuid" } },
          { "name": "inspector_id", "in": "query", "schema": { "type": "string", "format": "uuid" } },
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } },
          { "name": "per_page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100 } }
        ],
        "responses": {
          "200": {
            "description": "Paginated inspections",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Inspection" } }, "meta": { "type": "object" } } } } }
          }
        }
      }
    },
    "/inspections/{id}": {
      "parameters": [
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
      ],
      "get": { "summary": "Get inspection with observations", "responses": { "200": { "description": "ok" } } }
    },
    "/inspections/{id}/observations": {
      "parameters": [
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
      ],
      "get": { "summary": "List observations for inspection", "responses": { "200": { "description": "ok" } } },
      "post": {
        "summary": "Add observation",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["description"],
                "properties": {
                  "description": { "type": "string" },
                  "corrective_action": { "type": "string" },
                  "severity": { "type": "string" },
                  "status": { "type": "string" },
                  "location": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/observations/{id}": {
      "parameters": [
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
      ],
      "patch": { "summary": "Update observation", "responses": { "200": { "description": "ok" } } },
      "delete": { "summary": "Delete observation", "responses": { "200": { "description": "ok" } } }
    },
    "/inspections/{id}/report": {
      "parameters": [
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
      ],
      "get": {
        "summary": "Get latest report signed URL",
        "responses": {
          "200": {
            "description": "Signed URL for the rendered PDF",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string" },
                        "version": { "type": "integer" },
                        "signed_url": { "type": "string", "format": "uri", "nullable": true }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": { "description": "Report not ready yet" }
        }
      }
    },
    "/webhooks": {
      "get": { "summary": "List webhooks", "responses": { "200": { "description": "ok" } } },
      "post": {
        "summary": "Create webhook",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name", "target_url", "events"],
                "properties": {
                  "name": { "type": "string" },
                  "target_url": { "type": "string", "format": "uri" },
                  "events": { "type": "array", "items": { "type": "string" } },
                  "is_active": { "type": "boolean" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/webhooks/{id}": {
      "parameters": [
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
      ],
      "delete": { "summary": "Delete webhook", "responses": { "200": { "description": "ok" } } }
    },
    "/analytics/deficiencies": {
      "get": {
        "summary": "Top deficiencies",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 } }
        ],
        "responses": {
          "200": {
            "description": "Top deficiencies ranked by frequency",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "description": { "type": "string" },
                          "count": { "type": "integer" }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
