{
  "openapi": "3.1.0",
  "info": {
    "title": "Spark Public API",
    "version": "1.0.7",
    "description": "Public, read-only API for Spark (https://spark-v8.vercel.app), a social discovery app with reviewed profiles. These endpoints let developers and AI agents check service status and discover the API surface. Member data (profiles, matches, messages, calls) is never exposed here; it requires an authenticated member session in the Spark app. Rate limits: every response carries RFC RateLimit headers (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset); the advertised policy is 60 requests per 60 seconds per client. Exceeding it returns 429 with a Retry-After header. All errors use the Error schema (code, message, hint).",
    "contact": {
      "name": "NevetsInc (Birloi Eduard Stefan & Patrinoiu Calin Petre)",
      "url": "https://nevetsinc.vercel.app",
      "x-support": "https://nevetsinc.vercel.app/support"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://spark-v8.vercel.app",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Spark developer portal",
    "url": "https://spark-v8.vercel.app/developers"
  },
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "API discovery document",
        "description": "Returns a JSON index of the public API: available endpoints, the OpenAPI specification URL, the MCP endpoint, and related documentation links. Use this as the entry point for programmatic discovery.",
        "tags": [
          "discovery"
        ],
        "responses": {
          "200": {
            "description": "API index document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndexResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "description": "Maximum requests allowed in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 59
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "description": "Maximum requests allowed in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 59
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/status": {
      "get": {
        "operationId": "getServiceStatus",
        "summary": "Service liveness and version",
        "description": "Returns the current operational status of Spark, the service name, and the deployed version. Useful for health checks and monitoring. No authentication required.",
        "tags": [
          "status"
        ],
        "responses": {
          "200": {
            "description": "Service status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceStatusResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "description": "Maximum requests allowed in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 59
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "description": "Maximum requests allowed in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 59
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/mcp": {
      "post": {
        "operationId": "invokeMcpEndpoint",
        "summary": "Model Context Protocol endpoint",
        "description": "Streamable HTTP MCP endpoint (JSON-RPC 2.0). Supports the MCP handshake (initialize), notifications, tools/list, and tools/call. Currently exposes two read-only tools: spark_get_status and spark_get_api_index.",
        "tags": [
          "mcp"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "description": "Maximum requests allowed in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 59
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted (no response body)."
          },
          "405": {
            "description": "Method not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "description": "Maximum requests allowed in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": {
                  "type": "integer",
                  "example": 59
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer",
                  "example": 60
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ApiIndexResponse": {
        "type": "object",
        "description": "Discovery document for the Spark public API.",
        "required": [
          "name",
          "version",
          "endpoints"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Service name.",
            "example": "Spark"
          },
          "version": {
            "type": "string",
            "description": "Deployed service version.",
            "example": "1.0.7"
          },
          "description": {
            "type": "string",
            "description": "Human-readable summary of the API."
          },
          "endpoints": {
            "type": "array",
            "description": "Public endpoints available on this API.",
            "items": {
              "type": "object",
              "required": [
                "method",
                "path",
                "operationId",
                "description"
              ],
              "properties": {
                "method": {
                  "type": "string",
                  "description": "HTTP method.",
                  "example": "GET"
                },
                "path": {
                  "type": "string",
                  "description": "Endpoint path.",
                  "example": "/api/v1/status"
                },
                "operationId": {
                  "type": "string",
                  "description": "Unique operation identifier from the OpenAPI specification.",
                  "example": "getServiceStatus"
                },
                "description": {
                  "type": "string",
                  "description": "What the endpoint does."
                }
              }
            }
          },
          "links": {
            "type": "object",
            "description": "Related machine-readable resources.",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "openapi": "https://spark-v8.vercel.app/openapi.json",
              "mcp": "https://spark-v8.vercel.app/api/mcp"
            }
          }
        }
      },
      "ServiceStatusResponse": {
        "type": "object",
        "description": "Liveness and version information for the Spark service.",
        "required": [
          "name",
          "status",
          "version"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Service name.",
            "example": "Spark"
          },
          "status": {
            "type": "string",
            "description": "Operational status.",
            "enum": [
              "operational"
            ],
            "example": "operational"
          },
          "version": {
            "type": "string",
            "description": "Deployed service version.",
            "example": "1.0.7"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Server time when the response was generated."
          },
          "links": {
            "type": "object",
            "description": "Related resources.",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "description": "JSON-RPC 2.0 request for the MCP endpoint.",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ],
            "description": "JSON-RPC protocol version."
          },
          "id": {
            "description": "Request identifier (string, number, or null). Omit for notifications.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "method": {
            "type": "string",
            "description": "MCP method, e.g. initialize, tools/list, tools/call.",
            "example": "tools/list"
          },
          "params": {
            "type": "object",
            "description": "Method-specific parameters."
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "description": "JSON-RPC 2.0 response envelope.",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ]
          },
          "id": {
            "description": "Identifier echoed from the request.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "type": "object",
            "description": "Method result, present on success."
          },
          "error": {
            "type": "object",
            "description": "Error object, present on failure.",
            "properties": {
              "code": {
                "type": "integer",
                "description": "JSON-RPC error code."
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message."
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Structured error returned by every Spark API endpoint. Never HTML.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "hint"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code.",
                "example": "not_found"
              },
              "message": {
                "type": "string",
                "description": "Human-readable description of what went wrong.",
                "example": "No resource exists at this path."
              },
              "hint": {
                "type": "string",
                "description": "Actionable guidance for resolving the error.",
                "example": "See https://spark-v8.vercel.app/openapi.json for the list of valid endpoints."
              }
            }
          }
        }
      }
    },
    "responses": {
      "TooManyRequests": {
        "description": "Rate limit exceeded. Wait for the number of seconds given by Retry-After before retrying.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer",
              "example": 60
            }
          },
          "RateLimit-Limit": {
            "description": "Maximum requests allowed in the current window.",
            "schema": {
              "type": "integer",
              "example": 60
            }
          },
          "RateLimit-Remaining": {
            "description": "Requests remaining in the current window.",
            "schema": {
              "type": "integer",
              "example": 59
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the current window resets.",
            "schema": {
              "type": "integer",
              "example": 60
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Too many requests. The limit is 60 requests per 60 seconds.",
                "hint": "Wait for the number of seconds given by the Retry-After header, then retry."
              }
            }
          }
        }
      }
    }
  }
}
