{
  "openapi": "3.1.0",
  "info": {
    "title": "Aihoo! Public API",
    "version": "1.3.0",
    "description": "Public endpoints exposed by the Aihoo! GEO Performance Platform for AI agents and machine consumers. Developer portal: https://aihoo.app/developers. All error responses follow a typed JSON error model aligned with RFC 9457 (application/problem+json): every 4xx/5xx returns a machine-readable 'error' code and a human-readable 'message'. Every response carries standard rate-limit headers (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset); 429 responses add Retry-After. Versioning & deprecation policy: the API is versioned in this document; breaking changes are announced at https://aihoo.app/developers at least 90 days in advance and signalled in responses with Deprecation and Sunset (RFC 8594) headers.",
    "contact": {
      "name": "Aihoo!",
      "email": "contato@aihoo.app",
      "url": "https://aihoo.app/contato"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://aihoo.app/termos"
    }
  },
  "x-versioning": {
    "policy": "https://aihoo.app/developers#versionamento",
    "current": "1.2.0",
    "deprecationNoticeDays": 90,
    "sunsetHeaderConvention": "RFC 8594 (Deprecation + Sunset response headers)"
  },
  "servers": [
    {
      "url": "https://aihoo.app",
      "description": "Web origin (aliases /api/*)"
    },
    {
      "url": "https://egkekjdzyiytrwjvhadi.supabase.co/functions/v1",
      "description": "Edge Functions"
    }
  ],
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.0 with OpenID Connect. Authorization server metadata: https://aihoo.app/.well-known/oauth-authorization-server.json. Agent auth instructions: https://aihoo.app/auth.md",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://aihoo.app/.lovable/oauth/consent",
            "tokenUrl": "https://egkekjdzyiytrwjvhadi.supabase.co/auth/v1/token",
            "scopes": {
              "openid": "OpenID Connect identity",
              "profile": "Basic profile (name)",
              "email": "Email address",
              "mcp:read": "Read access to MCP tools (companies, audits, comparisons, tracked domains)"
            }
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Maximum requests allowed in the current rate-limit window.",
        "schema": {
          "type": "integer",
          "example": 30
        }
      },
      "RateLimitRemaining": {
        "description": "Requests remaining in the current window.",
        "schema": {
          "type": "integer",
          "example": 27
        }
      },
      "RateLimitReset": {
        "description": "Unix epoch (seconds) when the current window resets.",
        "schema": {
          "type": "integer",
          "example": 1787625660
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying after a 429 response.",
        "schema": {
          "type": "integer",
          "example": 42
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "Typed error object (RFC 9457 style). 'error' is the machine-readable code; 'message' is human-readable; 'retry_after_seconds' appears on 429.",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code, e.g. invalid_request, unauthenticated, not_authorized, not_found, quota_exceeded, rate_limited, payment_required"
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the failure and how to resolve it"
          },
          "retry_after_seconds": {
            "type": "integer",
            "description": "Seconds to wait before retrying (present on 429 responses)"
          }
        },
        "examples": [
          {
            "error": "quota_exceeded",
            "message": "Feature quota exceeded for this window.",
            "retry_after_seconds": 1800
          },
          {
            "error": "unauthenticated",
            "message": "Missing or expired bearer token."
          }
        ]
      },
      "JsonRpcRequest": {
        "type": "object",
        "description": "JSON-RPC 2.0 envelope used by the MCP server.",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "method": {
            "type": "string",
            "description": "e.g. initialize, tools/list, tools/call"
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "result": {
            "type": "object",
            "description": "Method result (server info, tool list or tool output)"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {
                "type": "object"
              }
            }
          }
        }
      },
      "GeoAuditRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "lang": {
            "type": "string",
            "enum": [
              "pt",
              "en",
              "es"
            ],
            "default": "pt"
          }
        }
      },
      "GeoAuditResult": {
        "type": "object",
        "description": "GEO audit report: overall score, sub-scores and a prioritized checklist.",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "overall_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "subscores": {
            "type": "object",
            "description": "Per-dimension scores (technical, content, entity, agent-readiness)"
          },
          "engine_scores": {
            "type": "object",
            "description": "Estimated citability per AI engine"
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "ok": {
                  "type": "boolean"
                },
                "severity": {
                  "type": "string",
                  "enum": [
                    "low",
                    "medium",
                    "high"
                  ]
                },
                "hint": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "X402PaymentRequired": {
        "type": "object",
        "description": "x402 payment requirements (https://x402.org) returned with HTTP 402.",
        "properties": {
          "x402Version": {
            "type": "integer"
          },
          "accepts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "scheme": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "maxAmountRequired": {
                  "type": "string"
                },
                "resource": {
                  "type": "string"
                },
                "payTo": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CompanionDocument": {
        "type": "string",
        "description": "Markdown or JSON companion document of a public page (same information hierarchy, machine-readable)."
      },
      "CatalogGeoResult": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string"
          },
          "score_current": {
            "type": "integer"
          },
          "score_optimized": {
            "type": "integer"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "score": {
                  "type": "integer"
                },
                "score_optimized": {
                  "type": "integer"
                },
                "current_value": {
                  "type": "string"
                },
                "suggested_value": {
                  "type": "string"
                },
                "origin": {
                  "type": "string"
                },
                "severity": {
                  "type": "string"
                },
                "rationale": {
                  "type": "string"
                }
              }
            }
          },
          "machine_read": {
            "type": "object"
          },
          "jsonld": {
            "type": "object"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request — fix the payload and retry",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or expired authentication token",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Authenticated but not authorized for this resource or plan",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource does not exist — see https://aihoo.app/sitemap.xml for valid URLs",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Per-user/feature quota exceeded — respect Retry-After and retry_after_seconds",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "ServerError": {
        "description": "Internal error — body still returns typed JSON",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/mcp": {
      "post": {
        "operationId": "invokeMcp",
        "summary": "MCP Server (Model Context Protocol, streamable HTTP)",
        "description": "OAuth 2.0-protected MCP server exposing Aihoo! tools: list_companies, latest_geo_audits, latest_domain_comparisons, list_tracked_domains, geo_audit, fetch_llms_txt. Rate limit: 30 calls/minute per user per tool. Server card: https://aihoo.app/.well-known/mcp/server-card.json",
        "security": [
          {
            "oauth2": [
              "openid",
              "profile",
              "email",
              "mcp:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response (result or typed error object)",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/serve-llms": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Get llms.txt content (summary or full)",
        "description": "Returns the curated markdown context index for aihoo.app. Public, cache-friendly.",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "summary",
                "full"
              ],
              "default": "summary"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown llms.txt document",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "description": "Markdown document following the llms.txt specification"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/widget": {
      "get": {
        "operationId": "getWidgetScript",
        "summary": "Embeddable Aihoo widget script",
        "description": "JavaScript bundle that renders the Aihoo! citation widget on customer sites.",
        "responses": {
          "200": {
            "description": "JS bundle",
            "content": {
              "application/javascript": {
                "schema": {
                  "type": "string",
                  "description": "Self-contained ES5-compatible widget bundle"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/geo-audit": {
      "post": {
        "operationId": "runGeoAudit",
        "summary": "Run a GEO audit on a URL",
        "description": "Full GEO/AEO readiness audit: overall score (0-100), sub-scores, engine citability estimates and a prioritized checklist.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GeoAuditRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audit result",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeoAuditResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-payment-info": {
          "intent": "charge",
          "method": [
            "tempo",
            "stripe",
            "card"
          ],
          "amount": "0.25",
          "currency": "USD",
          "protocols": [
            "x402",
            "mpp"
          ],
          "discovery": "https://aihoo.app/.well-known/x402.json"
        }
      }
    },
    "/x402-pay": {
      "get": {
        "operationId": "getX402PaymentRequirements",
        "summary": "x402 protected resource (returns 402 with payment requirements)",
        "description": "Demonstrates HTTP-native payments (x402): unpaid requests receive 402 with typed payment requirements; paid requests receive the protected content.",
        "responses": {
          "402": {
            "description": "Payment Required — typed x402 payment requirements",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/X402PaymentRequired"
                }
              }
            }
          },
          "200": {
            "description": "Paid content",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-payment-info": {
          "intent": "charge",
          "method": [
            "tempo",
            "stripe",
            "card"
          ],
          "amount": "0.25",
          "currency": "USD",
          "protocols": [
            "x402",
            "mpp"
          ],
          "discovery": "https://aihoo.app/.well-known/x402.json"
        }
      }
    },
    "/serve-page-companion": {
      "get": {
        "operationId": "getPageCompanion",
        "summary": "Markdown (.md) / JSON (.json) companion of any public page",
        "description": "Also reachable by appending .md or .json to any public URL, e.g. https://aihoo.app/geo.md. Unknown paths return a real HTTP 404 with a machine-readable body pointing to the sitemap and llms.txt.",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "md",
                "json"
              ]
            }
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Companion document",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/CompanionDocument"
                }
              },
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Structured companion (title, sections, links, entities)"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/catalog-geo-optimize": {
      "post": {
        "operationId": "optimizeCatalogProduct",
        "summary": "Otimização de catálogo GEO para e-commerce",
        "description": "Lê um produto como as IAs leem, pontua campo a campo e devolve a versão otimizada (PT-BR) pronta para aprovação, com JSON-LD Product/Offer completo.",
        "tags": [
          "commerce"
        ],
        "x-payment-info": {
          "intent": "charge",
          "method": [
            "tempo",
            "stripe",
            "card"
          ],
          "amount": "0.50",
          "currency": "USD",
          "protocols": [
            "x402",
            "mpp"
          ],
          "discovery": "https://aihoo.app/.well-known/x402.json"
        },
        "security": [
          {
            "oauth2": [
              "mcp:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "product_id": {
                    "type": "string"
                  },
                  "product_url": {
                    "type": "string"
                  },
                  "company_id": {
                    "type": "string"
                  },
                  "apply": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado da otimização",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogGeoResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "402": {
            "description": "Pagamento requerido (x402/MPP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/X402PaymentRequired"
                }
              }
            }
          }
        }
      }
    }
  },
  "x-payment": {
    "protocols": [
      "x402",
      "mpp"
    ],
    "facilitator": "https://x402.org/facilitator",
    "discovery": {
      "x402": "https://aihoo.app/.well-known/x402.json",
      "acp": "https://aihoo.app/.well-known/acp.json",
      "ucp": "https://aihoo.app/.well-known/ucp.json"
    },
    "sdk": {
      "typescript": "mppx",
      "python": "pymapp"
    }
  }
}