{
  "openapi": "3.0.3",
  "info": {
    "title": "Kevin Brown Insurance Agency — UCP Quote API",
    "description": "REST API for AI agents and developers to access New Jersey insurance quotes via the Universal Commerce Protocol (UCP). All endpoints are public. Coverage is available for New Jersey only (zip codes 07XXX and 08XXX). All quotes require a licensed human agent review with a 2–4 hour SLA.",
    "version": "2.2.0",
    "contact": {
      "name": "Kevin Brown Jr. — Licensed NJ Producer #3003694894",
      "email": "kevin@kevinbrowninsuranceagency.com",
      "url": "https://kevinbrowninsuranceagency.com"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://kevinbrowninsuranceagency.com/terms"
    },
    "x-llms-txt": "https://kevinbrowninsuranceagency.com/llms.txt",
    "x-ai-plugin": "https://kevinbrowninsuranceagency.com/.well-known/ai-plugin.json"
  },
  "servers": [
    {
      "url": "https://kevinbrowninsuranceagency.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Products",
      "description": "Discover available NJ insurance products and their required data fields"
    },
    {
      "name": "Quote Sessions",
      "description": "Create and manage insurance quote sessions. Sessions follow the state machine: draft → awaiting_client_info → awaiting_agent_review → agent_replied"
    }
  ],
  "paths": {
    "/api/products": {
      "get": {
        "tags": ["Products"],
        "summary": "List all NJ insurance products",
        "description": "Returns the full product catalog. Each product includes required_fields (data points needed to generate a quote), eligibility_rules (hard underwriting boundaries), and the UCP session endpoint. Call this first to understand what data to collect from the user.",
        "operationId": "listProducts",
        "responses": {
          "200": {
            "description": "Product catalog returned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductCatalogResponse"
                },
                "example": {
                  "agency": {
                    "name": "Kevin Brown Insurance Agency",
                    "license": "NJ Resident Producer #3003694894",
                    "territory": "New Jersey only (zip codes 07XXX, 08XXX)",
                    "sla_hours_min": 2,
                    "sla_hours_max": 4,
                    "human_in_loop": true
                  },
                  "products": [
                    {
                      "id": "auto",
                      "display_name": "Standard Auto (NJ)",
                      "vertical": "personal",
                      "required_fields": [
                        { "field_name": "vin", "type": "string", "description": "Vehicle Identification Number", "example": "1HGCM82..." },
                        { "field_name": "nj_zip", "type": "string", "description": "5-digit NJ Zip Code", "example": "07302" },
                        { "field_name": "driver_age", "type": "number", "description": "Age of primary operator", "example": 42 }
                      ],
                      "eligibility_rules": ["No more than 1 minor violation in 3 years", "Licensed in NJ for 3+ years"],
                      "ucp_session_endpoint": "/api/ucp/quote_sessions",
                      "ucp_style_support": true
                    }
                  ],
                  "total": 12
                }
              }
            }
          }
        }
      }
    },
    "/api/ucp/quote_sessions": {
      "post": {
        "tags": ["Quote Sessions"],
        "summary": "Create a new quote session",
        "description": "Initialises a new quote session for a specific insurance product. Returns a session ID and the list of missing_required_fields the agent still needs to collect from the user. Include callback_webhook_url to receive an async notification when the licensed agent responds (recommended over polling).",
        "operationId": "createQuoteSession",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSessionRequest"
              },
              "example": {
                "product_id": "auto",
                "initial_data": {
                  "nj_zip": "07302"
                },
                "contact_info": {
                  "first_name": "Alex",
                  "email": "alex@example.com"
                },
                "callback_webhook_url": "https://your-agent.ai/kbia-callback"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteSession"
                },
                "example": {
                  "id": "qs_abc123",
                  "product_id": "auto",
                  "state": "NJ",
                  "status": "awaiting_client_info",
                  "missing_required_fields": ["vin", "driver_age"],
                  "collected_data": { "nj_zip": "07302" },
                  "contact_info": { "first_name": "Alex", "email": "alex@example.com" },
                  "created_at": "2025-01-15T14:30:00Z",
                  "updated_at": "2025-01-15T14:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — bad product ID, non-NJ zip code, or missing required body fields",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "404": {
            "description": "Product ID not found — call GET /api/products for valid IDs",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/api/ucp/quote_sessions/{sessionId}": {
      "get": {
        "tags": ["Quote Sessions"],
        "summary": "Get session status",
        "description": "Returns the current state of a quote session including agent_response when the agent has replied. Polling interval: no more than once every 5 minutes. Prefer webhook callbacks over polling.",
        "operationId": "getQuoteSession",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "example": "qs_abc123"
          }
        ],
        "responses": {
          "200": {
            "description": "Session data returned",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QuoteSession" },
                "example": {
                  "id": "qs_abc123",
                  "status": "agent_replied",
                  "agent_response": {
                    "carrier_name": "Travelers NJ",
                    "preliminary_premium_estimate": "$89/month",
                    "agent_notes": "Qualifies for EV safe driver discount. Binder ready.",
                    "next_steps_url": "https://kevinbrowninsuranceagency.com/contact"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Session not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } }
            }
          }
        }
      },
      "patch": {
        "tags": ["Quote Sessions"],
        "summary": "Update session with collected data",
        "description": "Hydrates a session with data collected from the user. Use the missing_required_fields array from the GET or POST response to know what to collect next. Set ready_for_review: true only when all required fields and contact_info (first_name, last_name, email) are present — this triggers the 2–4 hour agent SLA.",
        "operationId": "updateQuoteSession",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "example": "qs_abc123"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UpdateSessionRequest" },
              "example": {
                "data": {
                  "vin": "1HGCM82633A123456",
                  "driver_age": 34
                },
                "contact_info": {
                  "last_name": "Johnson",
                  "phone": "732-555-0100"
                },
                "ready_for_review": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/UpdateSessionResponse" },
                "example": {
                  "id": "qs_abc123",
                  "status": "awaiting_agent_review",
                  "missing_required_fields": [],
                  "message": "Session submitted for agent review. A licensed NJ agent will respond within 2–4 hours."
                }
              }
            }
          },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "404": { "description": "Session not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProductCatalogResponse": {
        "type": "object",
        "properties": {
          "agency": { "$ref": "#/components/schemas/AgencyInfo" },
          "ai_instructions": { "type": "string", "description": "Operational guidelines for AI agents using this API" },
          "products": { "type": "array", "items": { "$ref": "#/components/schemas/ProductSpec" } },
          "total": { "type": "integer" }
        }
      },
      "AgencyInfo": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "example": "Kevin Brown Insurance Agency" },
          "license": { "type": "string", "example": "NJ Resident Producer #3003694894" },
          "territory": { "type": "string", "example": "New Jersey only (zip codes 07XXX, 08XXX)" },
          "sla_hours_min": { "type": "integer", "example": 2 },
          "sla_hours_max": { "type": "integer", "example": 4 },
          "human_in_loop": { "type": "boolean", "example": true }
        }
      },
      "FieldSpec": {
        "type": "object",
        "required": ["field_name", "type", "description", "example"],
        "properties": {
          "field_name": { "type": "string", "example": "vin" },
          "type": { "type": "string", "enum": ["string", "number", "boolean", "date", "enum"] },
          "description": { "type": "string", "example": "Vehicle Identification Number" },
          "example": { "type": "string", "example": "1HGCM82..." },
          "options": { "type": "array", "items": { "type": "string" }, "description": "Only present when type is enum" }
        }
      },
      "ProductSpec": {
        "type": "object",
        "required": ["id", "display_name", "vertical", "state", "ucp_session_endpoint"],
        "properties": {
          "id": { "type": "string", "example": "auto", "description": "Unique product slug — use this as product_id when creating sessions" },
          "display_name": { "type": "string", "example": "Standard Auto (NJ)" },
          "vertical": { "type": "string", "enum": ["personal", "commercial", "surplus"] },
          "state": { "type": "string", "enum": ["NJ"], "description": "Always NJ — KBIA is NJ-licensed only" },
          "description": { "type": "string" },
          "eligibility_rules": { "type": "array", "items": { "type": "string" } },
          "required_fields": { "type": "array", "items": { "$ref": "#/components/schemas/FieldSpec" } },
          "optional_fields": { "type": "array", "items": { "$ref": "#/components/schemas/FieldSpec" } },
          "recommended_add_ons": { "type": "array", "items": { "type": "string" } },
          "lead_sla_hours_min": { "type": "integer", "example": 2 },
          "lead_sla_hours_max": { "type": "integer", "example": 4 },
          "ucp_session_endpoint": { "type": "string", "example": "/api/ucp/quote_sessions" },
          "ucp_style_support": { "type": "boolean", "example": true }
        }
      },
      "ContactInfo": {
        "type": "object",
        "properties": {
          "first_name": { "type": "string", "example": "Alex" },
          "last_name": { "type": "string", "example": "Johnson" },
          "email": { "type": "string", "format": "email", "example": "alex@example.com" },
          "phone": { "type": "string", "example": "732-555-0100" }
        }
      },
      "CreateSessionRequest": {
        "type": "object",
        "required": ["product_id"],
        "properties": {
          "product_id": { "type": "string", "example": "auto", "description": "Must match an id from GET /api/products" },
          "initial_data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Any data already known. Include nj_zip if available for immediate NJ validation.",
            "example": { "nj_zip": "07302" }
          },
          "contact_info": { "$ref": "#/components/schemas/ContactInfo" },
          "callback_webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "Optional. If provided, this URL will receive a POST request when the agent responds. Strongly recommended over polling.",
            "example": "https://your-agent.ai/kbia-callback"
          }
        }
      },
      "UpdateSessionRequest": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Key/value pairs for fields listed in missing_required_fields",
            "example": { "vin": "1HGCM82633A123456", "driver_age": 34 }
          },
          "contact_info": { "$ref": "#/components/schemas/ContactInfo" },
          "ready_for_review": {
            "type": "boolean",
            "default": false,
            "description": "Set to true only when all required fields AND contact info (first_name, last_name, email) are present. Starts the 2–4 hour agent SLA."
          }
        }
      },
      "AgentResponse": {
        "type": "object",
        "description": "Populated by the licensed agent after reviewing the session. Only present when status is agent_replied.",
        "properties": {
          "carrier_name": { "type": "string", "example": "Travelers NJ" },
          "preliminary_premium_estimate": { "type": "string", "example": "$89/month", "description": "Agent-provided estimate only. Not a binding quote." },
          "agent_notes": { "type": "string" },
          "effective_date": { "type": "string", "format": "date" },
          "next_steps_url": { "type": "string", "format": "uri" },
          "binder_url": { "type": "string", "format": "uri", "description": "Present after full binding" }
        }
      },
      "QuoteSession": {
        "type": "object",
        "required": ["id", "product_id", "state", "status", "created_at", "updated_at"],
        "properties": {
          "id": { "type": "string", "example": "qs_abc123" },
          "product_id": { "type": "string", "example": "auto" },
          "state": { "type": "string", "enum": ["NJ"] },
          "status": {
            "type": "string",
            "enum": ["draft", "awaiting_client_info", "awaiting_agent_review", "agent_review_in_progress", "details_approved", "agent_replied", "rejected"],
            "description": "State machine: draft → awaiting_client_info → awaiting_agent_review → agent_replied"
          },
          "collected_data": { "type": "object", "additionalProperties": true },
          "contact_info": { "$ref": "#/components/schemas/ContactInfo" },
          "missing_required_fields": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Field names still needed from the user. Empty array means all required data is present."
          },
          "agent_response": { "$ref": "#/components/schemas/AgentResponse" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "UpdateSessionResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "status": { "type": "string" },
          "missing_required_fields": { "type": "array", "items": { "type": "string" } },
          "message": { "type": "string" }
        }
      },
      "WebhookPayload": {
        "type": "object",
        "description": "Payload sent to your callback_webhook_url when the agent replies",
        "properties": {
          "session_id": { "type": "string" },
          "status": { "type": "string", "example": "agent_replied" },
          "agent_response": { "$ref": "#/components/schemas/AgentResponse" }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "KBIA only accepts New Jersey risks (zip codes 07XXX, 08XXX)." }
        }
      }
    }
  },
  "x-agent-instructions": {
    "territory": "New Jersey only. Zip codes must start with 07 or 08.",
    "zero_hallucination": "Never provide premium amounts to the user. Only report what is in agent_response.preliminary_premium_estimate.",
    "human_in_loop": "All quotes require a licensed NJ agent review. Inform users of the 2-4 hour SLA.",
    "data_security": "Never collect SSNs, credit card numbers, or medical records via this API.",
    "session_flow": "1. GET /api/products → 2. POST /api/ucp/quote_sessions → 3. Collect missing_required_fields → 4. PATCH to hydrate → 5. PATCH with ready_for_review:true → 6. Receive webhook"
  }
}
