{
  "openapi": "3.1.0",
  "info": {
    "title": "Habait Hayehudi public content API",
    "version": "1.0.0",
    "description": "Read-only access to the public content of habaithayehudi.com (blog, partnerships), served by Supabase PostgREST. Candidate data is private and not exposed. Docs: https://habaithayehudi.com/docs",
    "contact": {
      "email": "contato@habaithayehudi.com.br",
      "url": "https://habaithayehudi.com/contact"
    },
    "x-scopes": {
      "read:blog": "Read published blog posts and categories.",
      "read:partnerships": "Read partnerships and member discounts."
    },
    "x-versioning-policy": "The API is versioned in the URL (/rest/v1). Breaking changes ship under a new version path (/rest/v2); the previous version is kept working on a best-effort basis for at least 90 days after the change is announced at https://habaithayehudi.com/docs and in https://habaithayehudi.com/llms.txt. Deprecated versions are marked in the docs, and, where the host supports it, with Deprecation and Sunset response headers."
  },
  "servers": [
    {
      "url": "https://bbhscnpjcwksqpcolglc.supabase.co/rest/v1",
      "description": "Supabase PostgREST"
    }
  ],
  "paths": {
    "/blog_posts": {
      "get": {
        "operationId": "listBlogPosts",
        "summary": "List published blog posts.",
        "description": "List published blog posts. Read-only; row-level security exposes only public rows.",
        "tags": [
          "Public content"
        ],
        "parameters": [
          {
            "name": "select",
            "in": "query",
            "description": "Comma-separated columns to return (PostgREST).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Ordering, e.g. data_publicacao.desc.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum rows to return.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "publicado",
            "in": "query",
            "description": "PostgREST filter, use eq.true.",
            "schema": {
              "type": "string",
              "examples": [
                "eq.true"
              ]
            }
          }
        ],
        "security": [
          {
            "apikey": [
              "read:blog"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Array of rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BlogPost"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid apikey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor the Retry-After header.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/blog_categorias": {
      "get": {
        "operationId": "listBlogCategories",
        "summary": "List blog categories.",
        "description": "List blog categories. Read-only; row-level security exposes only public rows.",
        "tags": [
          "Public content"
        ],
        "parameters": [
          {
            "name": "select",
            "in": "query",
            "description": "Comma-separated columns to return (PostgREST).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Ordering, e.g. nome.asc.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum rows to return.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "security": [
          {
            "apikey": [
              "read:blog"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Array of rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BlogCategory"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid apikey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor the Retry-After header.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/parcerias": {
      "get": {
        "operationId": "listPartnerships",
        "summary": "List partnerships and member discounts.",
        "description": "List partnerships and member discounts. Read-only; row-level security exposes only public rows.",
        "tags": [
          "Public content"
        ],
        "parameters": [
          {
            "name": "select",
            "in": "query",
            "description": "Comma-separated columns to return (PostgREST).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Ordering, e.g. ordem.asc.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum rows to return.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "security": [
          {
            "apikey": [
              "read:partnerships"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Array of rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Partnership"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid apikey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor the Retry-After header.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apikey": {
        "type": "apiKey",
        "in": "header",
        "name": "apikey",
        "description": "Public anon key used by the website (found in its JS bundle). Not a secret. Scopes are declared as role names in each operation security requirement (read:blog, read:partnerships); they are informational least-privilege labels (not separately enforced: the anon key can read every documented endpoint; row-level security limits which rows are public). Machine-readable: /.well-known/oauth-protected-resource."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable error."
          },
          "code": {
            "type": "string"
          },
          "hint": {
            "type": [
              "string",
              "null"
            ]
          },
          "details": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "BlogCategory": {
        "type": "object",
        "required": [
          "id",
          "nome",
          "slug"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BlogPost": {
        "type": "object",
        "required": [
          "id",
          "titulo",
          "slug"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "titulo": {
            "type": "string"
          },
          "titulo_en": {
            "type": [
              "string",
              "null"
            ]
          },
          "titulo_es": {
            "type": [
              "string",
              "null"
            ]
          },
          "titulo_he": {
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "type": "string"
          },
          "banner_url": {
            "type": "string",
            "format": "uri"
          },
          "conteudo": {
            "type": "string",
            "description": "HTML body (pt)."
          },
          "categoria_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "publicado": {
            "type": "boolean"
          },
          "data_publicacao": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "Partnership": {
        "type": "object",
        "required": [
          "id",
          "nome"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "cidade": {
            "type": "string"
          },
          "desconto": {
            "type": "string"
          },
          "link_externo": {
            "type": "string",
            "format": "uri"
          },
          "imagem_url": {
            "type": "string",
            "format": "uri"
          },
          "ordem": {
            "type": "integer"
          }
        }
      }
    }
  }
}