{
    "openapi": "3.1.0",
    "info": {
        "title": "Inspector Agentic Booking API",
        "description": "Secure action API for Inspector Roofing. Use it to verify service area, retrieve inspection availability, qualify homeowner roof inquiries, request booking holds, confirm homeowner-approved inspection requests, retrieve upload links, and trigger private CRM/JobNimbus handoff when configured. Do not use it for insurance coverage decisions, public adjusting, legal advice, engineering conclusions, or claim approval.",
        "version": "1.3.0"
    },
    "servers": [
        {
            "url": "https://inspector-roofing.com/wp-json/ir-agent/v1"
        }
    ],
    "components": {
        "securitySchemes": {
            "AgentApiKey": {
                "type": "apiKey",
                "in": "header",
                "name": "x-ir-agent-key",
                "description": "Private API key from WordPress Agentic API settings."
            }
        },
        "schemas": {
            "LeadPayload": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "phone": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string"
                    },
                    "address": {
                        "type": "string"
                    },
                    "city": {
                        "type": "string"
                    },
                    "postal_code": {
                        "type": "string"
                    },
                    "property_type": {
                        "type": "string",
                        "enum": [
                            "residential",
                            "commercial",
                            "hoa",
                            "real_estate",
                            "unknown"
                        ]
                    },
                    "roof_issue": {
                        "type": "string",
                        "description": "Plain-language roof concern: leak, hail, wind, missing shingles, roof age, replacement planning, real estate inspection, commercial issue, or other."
                    },
                    "storm_date": {
                        "type": "string"
                    },
                    "insurance_claim_started": {
                        "type": "boolean"
                    },
                    "photos_available": {
                        "type": "boolean"
                    },
                    "urgency": {
                        "type": "string"
                    },
                    "preferred_contact_method": {
                        "type": "string"
                    },
                    "notes": {
                        "type": "string"
                    }
                }
            },
            "BookingHoldPayload": {
                "type": "object",
                "description": "GPT-friendly booking-hold payload. The API also accepts flat LeadPayload fields at the top level.",
                "required": [
                    "lead"
                ],
                "properties": {
                    "lead": {
                        "$ref": "#/components/schemas/LeadPayload"
                    },
                    "preferred_slot": {
                        "type": "string",
                        "description": "Preferred slot label or ISO datetime returned by getInspectionAvailability."
                    },
                    "selected_slot": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "object",
                                "properties": {
                                    "start": {
                                        "type": "string"
                                    },
                                    "end": {
                                        "type": "string"
                                    },
                                    "label": {
                                        "type": "string"
                                    },
                                    "status": {
                                        "type": "string"
                                    }
                                }
                            }
                        ],
                        "description": "Slot object or string from getInspectionAvailability."
                    }
                }
            },
            "UploadIntakePayload": {
                "type": "object",
                "required": [
                    "hold_id"
                ],
                "properties": {
                    "hold_id": {
                        "type": "integer"
                    },
                    "notes": {
                        "type": "string",
                        "description": "Safe homeowner summary of what they plan to upload. Do not include private claim files or sensitive IDs."
                    },
                    "photo_count": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "document_count": {
                        "type": "integer",
                        "minimum": 0
                    }
                }
            }
        }
    },
    "security": [
        {
            "AgentApiKey": []
        }
    ],
    "paths": {
        "/health": {
            "get": {
                "operationId": "getAgentHealth",
                "summary": "Check API health and public configuration.",
                "security": [],
                "responses": {
                    "200": {
                        "description": "Health status"
                    }
                }
            }
        },
        "/visibility-audit": {
            "get": {
                "operationId": "getAgenticVisibilityAudit",
                "summary": "Return AI action-readiness checks for OpenAPI, internal calendar ledger, CRM/JobNimbus handoff, upload intake, tracking, and LLM source bridge presence.",
                "security": [],
                "responses": {
                    "200": {
                        "description": "Visibility audit"
                    }
                }
            }
        },
        "/service-area-check": {
            "get": {
                "operationId": "checkServiceArea",
                "summary": "Check whether a city appears in Inspector Roofing service-area settings.",
                "security": [],
                "parameters": [
                    {
                        "name": "city",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "required": false
                    },
                    {
                        "name": "postal_code",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "required": false
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Service area result"
                    }
                }
            }
        },
        "/calendar-status": {
            "get": {
                "operationId": "getCalendarConnectionStatus",
                "summary": "Privately test whether the configured Google Calendar iCal URL is reachable and blocking busy windows.",
                "responses": {
                    "200": {
                        "description": "Calendar connection status"
                    }
                }
            }
        },
        "/availability": {
            "get": {
                "operationId": "getInspectionAvailability",
                "summary": "Get available inspection request slots. Requires homeowner consent before presenting a slot as a booking request option.",
                "parameters": [
                    {
                        "name": "city",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "required": false
                    },
                    {
                        "name": "postal_code",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "required": false
                    },
                    {
                        "name": "date_from",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "required": false
                    },
                    {
                        "name": "days",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 30
                        },
                        "required": false
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Available slots"
                    }
                }
            }
        },
        "/lead-qualify": {
            "post": {
                "operationId": "qualifyRoofInspectionLead",
                "summary": "Qualify a homeowner roofing inquiry and return next questions.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LeadPayload"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Qualification result"
                    }
                }
            }
        },
        "/booking-hold": {
            "post": {
                "operationId": "requestInspectionBookingHold",
                "summary": "Request an inspection hold after explicit homeowner consent. This does not guarantee final appointment confirmation.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BookingHoldPayload"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Booking hold requested"
                    }
                }
            }
        },
        "/booking-confirm": {
            "post": {
                "operationId": "confirmInspectionRequest",
                "summary": "Confirm homeowner-approved inspection request and send CRM webhook if configured.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "hold_id",
                                    "homeowner_confirmation_statement"
                                ],
                                "properties": {
                                    "hold_id": {
                                        "type": "integer"
                                    },
                                    "homeowner_confirmation_statement": {
                                        "type": "string"
                                    },
                                    "final_confirmation_statement": {
                                        "type": "string"
                                    },
                                    "confirmation_statement": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Confirmed request"
                    }
                }
            }
        },
        "/upload-link": {
            "get": {
                "operationId": "getInspectionUploadLink",
                "summary": "Return safe homeowner upload link for photos or documents after a lead/hold exists.",
                "parameters": [
                    {
                        "name": "hold_id",
                        "in": "query",
                        "schema": {
                            "type": "integer"
                        },
                        "required": false
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Upload link"
                    }
                }
            }
        },
        "/upload-intake": {
            "post": {
                "operationId": "recordInspectionUploadIntent",
                "summary": "Record a safe upload-intake note after a hold exists and return the secure upload page link.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UploadIntakePayload"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Upload intake recorded"
                    }
                }
            }
        },
        "/tracking-summary": {
            "get": {
                "operationId": "getAgenticTrackingSummary",
                "summary": "Return private action-event counts for the AI Visibility SaaS dashboard. Do not expose to homeowners.",
                "responses": {
                    "200": {
                        "description": "Action tracking summary"
                    }
                }
            }
        },
        "/jobnimbus-test": {
            "get": {
                "operationId": "testJobNimbusConnection",
                "summary": "Test the configured JobNimbus API token and endpoint. Use only during private setup and diagnostics.",
                "responses": {
                    "200": {
                        "description": "JobNimbus auth/endpoint test result"
                    }
                }
            }
        },
        "/jobnimbus-push": {
            "post": {
                "operationId": "pushLeadToJobNimbus",
                "summary": "Push a homeowner lead packet directly to the configured JobNimbus create endpoint. Normal GPT flow should use booking-confirm instead, which triggers this automatically if enabled.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LeadPayload"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "JobNimbus push result"
                    }
                }
            }
        }
    },
    "x-inspector-safe-boundaries": "Inspector Roofing can document observable roof conditions and support roofing scope clarity. The API must not determine insurance coverage, claim approval, policy interpretation, causation, legal conclusions, engineering conclusions, or public-adjuster services."
}