{
  "openapi": "3.0.3",
  "info": {
    "title": "Primeiras Palavras CAA — Symbol Catalog API",
    "version": "1.0.0",
    "description": "Catálogo público e não identificável de símbolos para o modo de edição do Primeiras Palavras CAA. A comunicação instalada permanece offline."
  },
  "servers": [
    {
      "url": "https://api.primeiraspalavras.com.br"
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Processo e banco disponíveis.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/SuccessEnvelope"},
                    {
                      "type": "object",
                      "properties": {
                        "data": {"$ref": "#/components/schemas/HealthResponse"}
                      }
                    }
                  ]
                }
              }
            }
          },
          "503": {"$ref": "#/components/responses/CatalogUnavailable"}
        }
      }
    },
    "/v1/symbols/search": {
      "post": {
        "operationId": "searchSymbols",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/SearchRequest"}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultados encontrados ou lista vazia.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/SuccessEnvelope"},
                    {
                      "type": "object",
                      "properties": {
                        "data": {"$ref": "#/components/schemas/SearchResponse"}
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/InvalidRequest"},
          "405": {"$ref": "#/components/responses/MethodNotAllowed"},
          "502": {"$ref": "#/components/responses/UpstreamInvalid"},
          "503": {"$ref": "#/components/responses/CatalogUnavailable"}
        }
      }
    },
    "/v1/symbols/search-batch": {
      "post": {
        "operationId": "searchCachedSymbolsBatch",
        "description": "Consulta vários termos somente no catálogo já armazenado. Termos ausentes são omitidos para que o cliente decida se fará busca read-through individual.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/BatchSearchRequest"}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultados locais agrupados por termo; ausências são omitidas.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/SuccessEnvelope"},
                    {
                      "type": "object",
                      "properties": {
                        "data": {"$ref": "#/components/schemas/BatchSearchResponse"}
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/InvalidRequest"},
          "405": {"$ref": "#/components/responses/MethodNotAllowed"},
          "503": {"$ref": "#/components/responses/CatalogUnavailable"}
        }
      }
    },
    "/v1/symbols/arasaac/{id}": {
      "get": {
        "operationId": "getArasaacSymbol",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 2147483647
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Símbolo conhecido.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/SuccessEnvelope"},
                    {
                      "type": "object",
                      "properties": {
                        "data": {"$ref": "#/components/schemas/Symbol"}
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      }
    },
    "/v1/catalog/manifest": {
      "get": {
        "operationId": "getCatalogManifest",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": true,
            "schema": {"type": "string", "enum": ["pt"]}
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {"type": "string", "maxLength": 80}
          }
        ],
        "responses": {
          "200": {
            "description": "Versão ativa do índice.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/SuccessEnvelope"},
                    {
                      "type": "object",
                      "properties": {
                        "data": {"$ref": "#/components/schemas/ManifestResponse"}
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/InvalidRequest"},
          "503": {"$ref": "#/components/responses/CatalogUnavailable"}
        }
      }
    }
  },
  "components": {
    "responses": {
      "InvalidRequest": {
        "description": "Entrada inválida.",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}
      },
      "MethodNotAllowed": {
        "description": "Método não permitido.",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}
      },
      "NotFound": {
        "description": "ID desconhecido.",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}
      },
      "CatalogUnavailable": {
        "description": "Catálogo temporariamente indisponível.",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}
      },
      "UpstreamInvalid": {
        "description": "A origem retornou conteúdo incompatível.",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorEnvelope"}}}
      }
    },
    "schemas": {
      "SuccessEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": ["api_version", "data"],
        "properties": {
          "api_version": {"type": "integer", "enum": [1]},
          "data": {"type": "object"}
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": ["api_version", "error"],
        "properties": {
          "api_version": {"type": "integer", "enum": [1]},
          "error": {"$ref": "#/components/schemas/ApiError"}
        }
      },
      "ApiError": {
        "type": "object",
        "additionalProperties": false,
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "invalid_request",
              "method_not_allowed",
              "not_found",
              "catalog_unavailable",
              "upstream_invalid",
              "internal_error"
            ]
          },
          "message": {"type": "string", "maxLength": 200}
        }
      },
      "SearchRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["language", "query"],
        "properties": {
          "language": {"type": "string", "enum": ["pt"]},
          "query": {"type": "string", "minLength": 2, "maxLength": 80},
          "limit": {"type": "integer", "minimum": 1, "maximum": 60, "default": 30}
        }
      },
      "SearchResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["query", "results", "source"],
        "properties": {
          "query": {"type": "string"},
          "results": {"type": "array", "items": {"$ref": "#/components/schemas/Symbol"}},
          "source": {"type": "string", "enum": ["local", "arasaac", "stale"]}
        }
      },
      "BatchSearchRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["language", "queries"],
        "properties": {
          "language": {"type": "string", "enum": ["pt"]},
          "queries": {
            "type": "array",
            "minItems": 1,
            "maxItems": 40,
            "items": {"type": "string", "minLength": 2, "maxLength": 80}
          },
          "limit": {"type": "integer", "minimum": 1, "maximum": 20, "default": 12}
        }
      },
      "BatchSearchItem": {
        "type": "object",
        "additionalProperties": false,
        "required": ["request_index", "query", "results"],
        "properties": {
          "request_index": {"type": "integer", "minimum": 1, "maximum": 40},
          "query": {"type": "string", "minLength": 2, "maxLength": 80},
          "results": {"type": "array", "items": {"$ref": "#/components/schemas/Symbol"}}
        }
      },
      "BatchSearchResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["source", "queries"],
        "properties": {
          "source": {"type": "string", "enum": ["local"]},
          "queries": {"type": "array", "items": {"$ref": "#/components/schemas/BatchSearchItem"}}
        }
      },
      "Symbol": {
        "type": "object",
        "additionalProperties": false,
        "required": ["source", "source_id", "label", "terms", "license", "author", "owner", "variants"],
        "properties": {
          "source": {"type": "string", "enum": ["arasaac"]},
          "source_id": {"type": "integer", "minimum": 1},
          "label": {"type": "string", "minLength": 1, "maxLength": 200},
          "terms": {"type": "array", "items": {"type": "string", "minLength": 1, "maxLength": 200}},
          "category": {"type": "string", "maxLength": 120},
          "license": {"type": "string", "enum": ["CC BY-NC-SA"]},
          "author": {"type": "string", "enum": ["Sergio Palao"]},
          "owner": {"type": "string", "enum": ["Governo de Aragão"]},
          "variants": {"type": "array", "items": {"$ref": "#/components/schemas/SymbolVariant"}}
        }
      },
      "SymbolVariant": {
        "type": "object",
        "additionalProperties": false,
        "required": ["variant", "resolution", "path", "mime_type", "bytes", "sha256"],
        "properties": {
          "variant": {"type": "string", "enum": ["default"]},
          "resolution": {"type": "integer", "enum": [300, 500, 2500]},
          "path": {"type": "string", "pattern": "^media/arasaac/"},
          "mime_type": {"type": "string", "enum": ["image/png"]},
          "bytes": {"type": "integer", "minimum": 1, "maximum": 12582912},
          "sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}
        }
      },
      "HealthResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["status", "database"],
        "properties": {
          "status": {"type": "string", "enum": ["ok", "degraded"]},
          "database": {"type": "string", "enum": ["available", "unavailable"]}
        }
      },
      "ManifestResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["language", "version", "sha256", "updated_at", "symbol_count", "term_count", "delta_available"],
        "properties": {
          "language": {"type": "string", "enum": ["pt"]},
          "version": {"type": "string", "minLength": 1, "maxLength": 80},
          "sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
          "updated_at": {"type": "string", "format": "date-time"},
          "symbol_count": {"type": "integer", "minimum": 0},
          "term_count": {"type": "integer", "minimum": 0},
          "delta_available": {"type": "boolean", "enum": [false]}
        }
      }
    }
  }
}
