{
  "openapi": "3.1.0",
  "info": {
    "title": "Healthspan Score API",
    "version": "1.0.0",
    "summary": "PlanScout intake scoring and Genworth cost-of-care analysis",
    "description": "Receives PlanScout intake events, produces versioned person and household Healthspan scores, and delivers results through an asynchronous callback. The API also exposes the existing Genworth 2024 care-analysis model as a standalone operation.",
    "contact": {
      "name": "Black Flag Design",
      "url": "https://blackflag.design"
    }
  },
  "servers": [
    {
      "url": "https://blessed-squirrel-650.convex.site",
      "description": "Active QA deployment"
    }
  ],
  "tags": [
    {
      "name": "Integration",
      "description": "PlanScout intake and score status"
    },
    {
      "name": "Care analysis",
      "description": "Genworth 2024 cost-of-care model"
    },
    {
      "name": "Operations",
      "description": "Deployment readiness"
    }
  ],
  "paths": {
    "/oauth/token": {
      "post": {
        "tags": [
          "Integration"
        ],
        "operationId": "issuePlanScoutAccessToken",
        "summary": "Exchange PlanScout machine credentials for a Clerk M2M token",
        "description": "Implements the OAuth 2.0 client-credentials request shape requested by PlanScout. The opaque bearer token is issued and verified by Clerk M2M authentication and expires after one hour.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "const": "client_credentials"
                  },
                  "scope": {
                    "type": "string",
                    "const": "healthspan.intakes.write"
                  },
                  "client_id": {
                    "type": "string",
                    "description": "Optional when HTTP Basic authentication is used."
                  },
                  "client_secret": {
                    "type": "string",
                    "format": "password",
                    "description": "Optional when HTTP Basic authentication is used."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Clerk M2M access token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthTokenResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/OAuthError"
          },
          "401": {
            "$ref": "#/components/responses/OAuthError"
          }
        }
      }
    },
    "/v1/intakes": {
      "post": {
        "tags": [
          "Integration"
        ],
        "operationId": "submitPlanScoutIntake",
        "summary": "Accept a PlanScout intake for asynchronous scoring",
        "description": "Production requests use a Clerk-backed OAuth 2.0 client-credentials bearer token. HMAC-SHA256 remains available as a compatibility fallback. Delivery is at least once; duplicate eventId values return the original status without creating a second score or callback.",
        "security": [
          {
            "planScoutOAuth": [
              "healthspan.intakes.write"
            ]
          },
          {
            "planScoutHmac": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PlanScoutTimestamp"
          },
          {
            "$ref": "#/components/parameters/PlanScoutSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlanScoutIntake"
              },
              "examples": {
                "complete": {
                  "summary": "Complete synthetic intake",
                  "value": {
                    "eventType": "intake.submitted",
                    "eventId": "f1c2e0a4-9b6d-4f2a-8e21-2c7b9a0d4e55",
                    "eventTimestamp": "2026-07-10T16:30:00.000Z",
                    "schemaVersion": "v1",
                    "advisorId": "10482",
                    "clientGuid": "b7e63d4a-1f88-4c0e-9a2f-3d51c6e9aa10",
                    "planscoutPlanRequestId": "665f0a1b2c3d4e5f60718293",
                    "advisor": {
                      "name": "Jane Advisor",
                      "company": "Summit Wealth Partners",
                      "email": "jane@summitwealth.example"
                    },
                    "client": {
                      "hasPartner": true,
                      "primary": {
                        "firstName": "Robert",
                        "lastName": "Miyazaki",
                        "age": 64
                      },
                      "partner": {
                        "firstName": "Susan",
                        "lastName": "Miyazaki",
                        "age": 61
                      }
                    },
                    "intake": {
                      "employment": {
                        "primary": {
                          "isRetired": false,
                          "currentIncome": 145000,
                          "expectedRetirementAge": 67
                        },
                        "partner": {
                          "isRetired": false,
                          "currentIncome": 60000,
                          "expectedRetirementAge": 65
                        }
                      },
                      "savings": {
                        "totalAssets": 1170000
                      },
                      "goals": {
                        "targetIncome": 164000,
                        "legacyGoal": 250000
                      }
                    },
                    "healthSupport": {
                      "schemaVersion": "v1",
                      "answers": [
                        {
                          "key": "diet_frequency",
                          "questionId": "HQ1",
                          "type": "single_choice_scale",
                          "subject": "primary",
                          "selected": {
                            "value": "often",
                            "label": "Often",
                            "ordinal": 3
                          }
                        },
                        {
                          "key": "community_connection",
                          "questionId": "HQ2",
                          "type": "single_choice_scale",
                          "subject": "primary",
                          "selected": {
                            "value": "somewhat_connected",
                            "label": "Somewhat connected",
                            "ordinal": 2
                          }
                        },
                        {
                          "key": "health_conditions",
                          "questionId": "HQ3",
                          "type": "multi_select",
                          "subject": "primary",
                          "selected": [
                            {
                              "value": "hypertension",
                              "label": "Hypertension"
                            }
                          ],
                          "noneSelected": false
                        },
                        {
                          "key": "care_reliance",
                          "questionId": "HQ4",
                          "type": "multi_select",
                          "subject": "primary",
                          "selected": [
                            {
                              "value": "spouse_partner",
                              "label": "Spouse / partner"
                            },
                            {
                              "value": "adult_child",
                              "label": "Adult child"
                            }
                          ]
                        },
                        {
                          "key": "care_dependents",
                          "questionId": "HQ5",
                          "type": "multi_select",
                          "subject": "primary",
                          "selected": [
                            {
                              "value": "parent",
                              "label": "Parent"
                            }
                          ]
                        },
                        {
                          "key": "emergency_contact",
                          "questionId": "HQ6",
                          "type": "single_choice_with_name",
                          "subject": "primary",
                          "selected": {
                            "value": "adult_child",
                            "label": "Adult child"
                          },
                          "contactName": "Emily Miyazaki"
                        }
                      ]
                    },
                    "healthspan": {
                      "state": "Colorado",
                      "careAssessment": {
                        "conditionSummary": "Hypertension managed with medication",
                        "cognitionStage": "none",
                        "adlGrid": {
                          "bathing": "independent",
                          "dressing": "independent",
                          "toileting": "independent",
                          "transferring": "independent",
                          "continence": "independent",
                          "feeding": "independent"
                        },
                        "iadlGrid": {
                          "medication_management": "cueing",
                          "meal_prep": "independent",
                          "housekeeping": "assist",
                          "shopping": "independent",
                          "transportation": "independent",
                          "finances": "independent",
                          "communication": "independent"
                        },
                        "riskFlags": [],
                        "dmeInUse": [],
                        "caregiverHoursPerWeek": 20,
                        "carePreferences": "Remain at home as long as practical",
                        "state": "Colorado"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Duplicate event already accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptedResponse"
                }
              }
            }
          },
          "202": {
            "description": "Accepted for scoring",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/v1/intakes/{eventId}": {
      "get": {
        "tags": [
          "Integration"
        ],
        "operationId": "getIntakeStatus",
        "summary": "Read score and callback status by PlanScout event ID",
        "security": [
          {
            "planScoutOAuth": [
              "healthspan.intakes.write"
            ]
          },
          {
            "planScoutHmac": []
          }
        ],
        "parameters": [
          {
            "name": "eventId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current processing state with generated callback payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntakeStatus"
                }
              }
            }
          },
          "404": {
            "description": "Event not found"
          }
        }
      }
    },
    "/v1/care-cost/estimate": {
      "post": {
        "tags": [
          "Care analysis"
        ],
        "operationId": "estimateCareCost",
        "summary": "Run the Genworth 2024 care-needs and cost model",
        "description": "Derives weekly care needs, matches appropriate settings to state median costs, and generates multi-stage care scenarios.",
        "security": [
          {
            "planScoutOAuth": [
              "healthspan.intakes.write"
            ]
          },
          {
            "planScoutHmac": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CareAssessment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Care analysis result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": [
          "Operations"
        ],
        "operationId": "getHealth",
        "summary": "Check API readiness",
        "responses": {
          "200": {
            "description": "Healthy deployment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "planScoutOAuth": {
        "type": "oauth2",
        "description": "PlanScout machine authentication. Exchange client credentials at the token endpoint, cache the returned Clerk M2M bearer token until expiry, and send it in the Authorization header.",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://blessed-squirrel-650.convex.site/oauth/token",
            "scopes": {
              "healthspan.intakes.write": "Submit intakes and read scoring status."
            }
          }
        }
      },
      "planScoutHmac": {
        "type": "apiKey",
        "in": "header",
        "name": "X-PlanScout-Signature",
        "description": "sha256=<hex HMAC-SHA256(secret, timestamp + '.' + rawBody)>. Pair with X-PlanScout-Timestamp; requests more than five minutes old are rejected."
      }
    },
    "parameters": {
      "PlanScoutTimestamp": {
        "name": "X-PlanScout-Timestamp",
        "in": "header",
        "required": false,
        "schema": {
          "type": "integer",
          "format": "int64"
        },
        "description": "Current Unix time in seconds."
      },
      "PlanScoutSignature": {
        "name": "X-PlanScout-Signature",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "pattern": "^sha256=[0-9a-f]{64}$"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed JSON or request headers",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, expired, or invalid bearer token or HMAC signature",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "OAuthError": {
        "description": "OAuth client authentication or token request failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/OAuthError"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "Payload does not satisfy schema v1",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "OAuthTokenResponse": {
        "type": "object",
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "scope"
        ],
        "properties": {
          "access_token": {
            "type": "string",
            "description": "Opaque Clerk M2M token."
          },
          "token_type": {
            "type": "string",
            "const": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3600
          },
          "scope": {
            "type": "string",
            "const": "healthspan.intakes.write"
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "required": [
          "error",
          "error_description"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "error_description": {
            "type": "string"
          }
        }
      },
      "PlanScoutIntake": {
        "type": "object",
        "required": [
          "eventType",
          "eventId",
          "eventTimestamp",
          "schemaVersion",
          "advisorId",
          "clientGuid",
          "planscoutPlanRequestId",
          "advisor",
          "client",
          "intake",
          "healthSupport"
        ],
        "properties": {
          "eventType": {
            "const": "intake.submitted"
          },
          "eventId": {
            "type": "string",
            "format": "uuid"
          },
          "eventTimestamp": {
            "type": "string",
            "format": "date-time"
          },
          "schemaVersion": {
            "const": "v1"
          },
          "advisorId": {
            "type": "string"
          },
          "clientGuid": {
            "type": "string",
            "format": "uuid"
          },
          "planscoutPlanRequestId": {
            "type": "string"
          },
          "advisor": {
            "type": "object",
            "additionalProperties": true
          },
          "client": {
            "type": "object",
            "additionalProperties": true
          },
          "intake": {
            "type": "object",
            "additionalProperties": true
          },
          "estimatesApplied": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "estimatedValues": {
            "type": "object",
            "additionalProperties": true
          },
          "healthSupport": {
            "type": "object",
            "required": [
              "schemaVersion",
              "answers"
            ],
            "properties": {
              "schemaVersion": {
                "const": "v1"
              },
              "answers": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "$ref": "#/components/schemas/HealthAnswer"
                }
              }
            }
          },
          "healthspan": {
            "type": "object",
            "description": "Optional extension for state-specific Genworth care analysis.",
            "properties": {
              "state": {
                "type": "string"
              },
              "careAssessment": {
                "$ref": "#/components/schemas/CareAssessment"
              }
            }
          }
        },
        "additionalProperties": true
      },
      "HealthAnswer": {
        "type": "object",
        "required": [
          "key",
          "questionId",
          "subject"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "questionId": {
            "type": "string",
            "examples": [
              "HQ1"
            ]
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "enum": [
              "primary",
              "partner"
            ]
          },
          "selected": {},
          "noneSelected": {
            "type": "boolean"
          },
          "otherText": {
            "type": [
              "string",
              "null"
            ]
          },
          "contactName": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "CareAssessment": {
        "type": "object",
        "required": [
          "conditionSummary",
          "cognitionStage",
          "adlGrid",
          "iadlGrid",
          "riskFlags",
          "dmeInUse",
          "caregiverHoursPerWeek",
          "carePreferences",
          "state"
        ],
        "properties": {
          "conditionSummary": {
            "type": "string"
          },
          "cognitionStage": {
            "type": "string",
            "enum": [
              "none",
              "mci",
              "mild_dementia",
              "moderate_dementia",
              "severe_dementia"
            ]
          },
          "adlGrid": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/AbilityLevel"
            }
          },
          "iadlGrid": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/AbilityLevel"
            }
          },
          "riskFlags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "dmeInUse": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "caregiverHoursPerWeek": {
            "type": "number",
            "minimum": 0,
            "maximum": 168
          },
          "carePreferences": {
            "type": "string"
          },
          "state": {
            "type": "string"
          }
        }
      },
      "AbilityLevel": {
        "type": "string",
        "enum": [
          "independent",
          "cueing",
          "assist",
          "dependent"
        ]
      },
      "AcceptedResponse": {
        "type": "object",
        "required": [
          "accepted",
          "eventId",
          "duplicate",
          "status",
          "statusUrl"
        ],
        "properties": {
          "accepted": {
            "const": true
          },
          "eventId": {
            "type": "string",
            "format": "uuid"
          },
          "duplicate": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "completed"
            ]
          },
          "statusUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "IntakeStatus": {
        "type": "object",
        "properties": {
          "eventId": {
            "type": "string",
            "format": "uuid"
          },
          "scoreStatus": {
            "type": "string"
          },
          "callbackStatus": {
            "type": "string"
          },
          "score": {
            "type": "object",
            "additionalProperties": true
          },
          "callback": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      }
    }
  }
}