{
  "openapi": "3.0.3",
  "info": {
    "title": "FeedIRL Discovery API",
    "version": "1.1.0",
    "description": "Public discovery layer for AI agents. Ranked upcoming events with attribution referral links, fit reasons, honest field status, and MCP tool discover_events. FeedIRL does not process ticket payments.",
    "contact": {
      "email": "support@feedirl.com",
      "url": "https://www.feedirl.com"
    }
  },
  "servers": [
    {
      "url": "https://www.feedirl.com/api/v1/discover",
      "description": "Canonical public endpoint"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "summary": "Discover events",
        "operationId": "discoverEvents",
        "parameters": [
          { "name": "lat", "in": "query", "schema": { "type": "number" } },
          { "name": "lng", "in": "query", "schema": { "type": "number" } },
          { "name": "city", "in": "query", "schema": { "type": "string" } },
          {
            "name": "date",
            "in": "query",
            "schema": { "type": "string", "format": "date" },
            "description": "Start date YYYY-MM-DD"
          },
          {
            "name": "end_date",
            "in": "query",
            "schema": { "type": "string", "format": "date" }
          },
          {
            "name": "interests",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Comma-separated keywords / vibe"
          },
          { "name": "category", "in": "query", "schema": { "type": "string" } },
          { "name": "keywords", "in": "query", "schema": { "type": "string" } },
          {
            "name": "budget",
            "in": "query",
            "schema": { "type": "number" },
            "description": "Max price USD"
          },
          {
            "name": "exclude_adult",
            "in": "query",
            "schema": { "type": "boolean", "default": true }
          },
          {
            "name": "include_adult",
            "in": "query",
            "schema": { "type": "boolean", "default": false }
          },
          {
            "name": "radius_mi",
            "in": "query",
            "schema": { "type": "number", "default": 25 }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "default": 20, "maximum": 50 }
          },
          {
            "name": "attendees",
            "in": "query",
            "schema": { "type": "integer" },
            "description": "Reserved for future ranking"
          },
          { "name": "ai_provider", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Ranked discovery results with referral_url, reason, verified_at" },
          "400": { "description": "Missing query" },
          "429": { "description": "Rate limited (60/min/IP)" }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "summary": "OpenAPI document",
        "operationId": "getOpenApi",
        "responses": { "200": { "description": "OpenAPI 3 JSON" } }
      }
    },
    "/mcp": {
      "post": {
        "summary": "MCP JSON-RPC (discover_events)",
        "operationId": "mcpDiscoverEvents",
        "responses": { "200": { "description": "JSON-RPC MCP response" } }
      }
    },
    "/conversions": {
      "post": {
        "summary": "Partner conversion webhook (verified purchases only)",
        "operationId": "recordConversion",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "attribution_id": { "type": "string" },
                  "event_id": { "type": "string", "format": "uuid" },
                  "partner": { "type": "string" },
                  "external_order_id": { "type": "string" },
                  "amount_cents": { "type": "integer" },
                  "currency": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Recorded" } }
      }
    }
  }
}
