{
  "openapi": "3.1.0",
  "info": {
    "title": "Senior Call API",
    "version": "1.0.0",
    "summary": "Public read-only product API plus the authenticated MCP agent surface for Senior Call.",
    "description": "Senior Call provides automated daily wellness check-in calls for people who live alone.\n\nTwo surfaces are documented here:\n\n1. **Public read-only API** (`/functions/v1/public-api`) \u2014 no authentication, no customer data. Static product facts for agents: status, plans, service description.\n2. **MCP endpoint** (`/functions/v1/mcp`) \u2014 authenticated agent access to the caller's own Senior Call data via the Model Context Protocol, using OAuth 2.1 with named, least-privilege scopes. Row-level security means callers only ever see records they are already permitted to see.\n\nAll errors are returned as JSON with a machine-readable `error.code`, a human message, and a `resolution` hint.",
    "contact": {
      "name": "Senior Call support",
      "url": "https://seniorcall.io/contact",
      "email": "support@seniorcall.io"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://seniorcall.io/terms"
    }
  },
  "servers": [
    {
      "url": "https://ljwgabkowvyqgmwlgciz.functions.supabase.co",
      "description": "Senior Call API (production edge functions host)"
    },
    {
      "url": "https://seniorcall.io",
      "description": "Website and machine-readable metadata files (/openapi.json, /llms.txt, /sitemap.xml)"
    }
  ],
  "externalDocs": {
    "description": "Plain-text agent brief",
    "url": "https://seniorcall.io/llms.txt"
  },
  "tags": [
    {
      "name": "public",
      "description": "Unauthenticated public product information."
    },
    {
      "name": "mcp",
      "description": "Authenticated Model Context Protocol endpoint."
    }
  ],
  "paths": {
    "/public-api": {
      "get": {
        "tags": [
          "public"
        ],
        "operationId": "getApiIndex",
        "summary": "API index",
        "description": "Lists the available public endpoints and pointers to machine-readable metadata.",
        "security": [],
        "responses": {
          "200": {
            "description": "API index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "service": "Senior Call public API",
                  "version": "1.0.0",
                  "endpoints": [
                    "/v1/status",
                    "/v1/plans",
                    "/v1/service"
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/public-api/v1/status": {
      "get": {
        "tags": [
          "public"
        ],
        "operationId": "getStatus",
        "summary": "Service health",
        "security": [],
        "responses": {
          "200": {
            "description": "Service is reachable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "service": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "status": "ok",
                  "service": "senior-call-public-api",
                  "version": "1.0.0"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/public-api/v1/plans": {
      "get": {
        "tags": [
          "public"
        ],
        "operationId": "listPlans",
        "summary": "List published plans and prices",
        "security": [],
        "responses": {
          "200": {
            "description": "Published plans.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "currency",
                    "plans"
                  ],
                  "properties": {
                    "currency": {
                      "type": "string",
                      "example": "USD"
                    },
                    "plans": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Plan"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/public-api/v1/service": {
      "get": {
        "tags": [
          "public"
        ],
        "operationId": "getServiceDescription",
        "summary": "Service description, coverage and escalation policy",
        "security": [],
        "responses": {
          "200": {
            "description": "Service description.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Service"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": [
          "mcp"
        ],
        "operationId": "mcpJsonRpc",
        "summary": "Model Context Protocol endpoint (JSON-RPC 2.0)",
        "description": "Streamable-HTTP MCP endpoint. Requires an OAuth 2.1 bearer token issued by the Senior Call authorization server. Available tools: `whoami`, `list_seniors`, `get_senior`, `list_recent_calls`, `list_open_incidents`. All tools are read-only and scoped to what the authenticated caller may already access. Protected-resource metadata (including `scopes_supported`) is published at `/.well-known/oauth-protected-resource` per RFC 9728.",
        "security": [
          {
            "oauth2": [
              "profile:read"
            ]
          },
          {
            "oauth2": [
              "seniors:read"
            ]
          },
          {
            "oauth2": [
              "calls:read"
            ]
          },
          {
            "oauth2": [
              "incidents:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "string",
                      "number"
                    ]
                  },
                  "method": {
                    "type": "string",
                    "example": "tools/list"
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 with PKCE. Request only the scopes the agent needs; all Senior Call scopes are read-only and further constrained by row-level security.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://seniorcall.io/oauth/authorize",
            "tokenUrl": "https://seniorcall.io/oauth/token",
            "refreshUrl": "https://seniorcall.io/oauth/token",
            "scopes": {
              "profile:read": "Read the caller's own Senior Call identity: user id, email and role.",
              "seniors:read": "Read the SC member records the caller is already permitted to see.",
              "calls:read": "Read wellness check-in call history for those members.",
              "incidents:read": "Read open welfare-check incidents for those members."
            }
          }
        }
      }
    },
    "schemas": {
      "Plan": {
        "type": "object",
        "required": [
          "id",
          "name",
          "price_usd"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "essential_monthly"
          },
          "name": {
            "type": "string"
          },
          "price_usd": {
            "type": "number",
            "example": 9.99
          },
          "regular_price_usd": {
            "type": "number",
            "example": 14.99
          },
          "interval": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "month",
              "year",
              null
            ]
          },
          "trial_days": {
            "type": [
              "integer",
              "null"
            ],
            "example": 7
          },
          "charged_during_trial": {
            "type": "boolean",
            "example": false
          },
          "includes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Service": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "legal_name": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "coverage": {
            "type": "object"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "phone": {
            "type": "string",
            "example": "+13024558009"
          },
          "website": {
            "type": "string",
            "format": "uri"
          },
          "max_daily_checkins": {
            "type": "integer",
            "example": 2
          },
          "escalation": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "status"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code.",
                "enum": [
                  "not_found",
                  "method_not_allowed",
                  "unauthorized",
                  "forbidden",
                  "invalid_request",
                  "rate_limited",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              },
              "resolution": {
                "type": "string",
                "description": "What the agent should do next."
              },
              "status": {
                "type": "integer",
                "description": "HTTP status code."
              },
              "documentation_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    },
    "responses": {
      "NotFound": {
        "description": "Resource does not exist.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "No public API resource exists at '/v1/nope'.",
                "resolution": "See the endpoint list at /functions/v1/public-api or the OpenAPI document at /openapi.json.",
                "status": 404,
                "documentation_url": "https://seniorcall.io/openapi.json"
              }
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "This API is read-only.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "method_not_allowed",
                "message": "HTTP POST is not supported by this endpoint.",
                "resolution": "This API is read-only. Retry with GET.",
                "status": 405,
                "documentation_url": "https://seniorcall.io/openapi.json"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid bearer token.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Token lacks the required scope, or row-level security denies the record.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "security": []
}
