{
  "openapi": "3.1.0",
  "info": {
    "version": "e5faaf6d"
  },
  "servers": [
    {
      "url": "https://editalmd.com"
    }
  ],
  "components": {
    "schemas": {
      "Saude": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "`true` quando a origem respondeu."
          },
          "acervo": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Acervo"
              }
            ],
            "description": "Números do acervo."
          },
          "preco_markdown_usd": {
            "type": "string",
            "description": "Preço vigente do documento recente."
          },
          "gratis_acima_de_dias": {
            "type": "integer",
            "description": "Idade a partir da qual o documento é amostra grátis."
          }
        },
        "required": [
          "ok",
          "acervo",
          "preco_markdown_usd",
          "gratis_acima_de_dias"
        ],
        "description": "Saúde do Worker e da origem."
      },
      "Acervo": {
        "type": "object",
        "properties": {
          "compras": {
            "type": "integer",
            "description": "Compras públicas indexadas."
          },
          "documentos_lidos": {
            "type": "integer",
            "description": "Documentos com texto extraído e disponível."
          }
        },
        "required": [
          "compras",
          "documentos_lidos"
        ],
        "description": "Tamanho do acervo lido na origem."
      },
      "Busca": {
        "type": "object",
        "properties": {
          "itens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Compra"
            },
            "description": "Compras que casaram com o termo."
          },
          "preco_markdown_usd": {
            "type": "string",
            "description": "Preço do documento recente."
          },
          "gratis_acima_de_dias": {
            "type": "integer",
            "description": "Janela de amostra grátis, em dias."
          },
          "pago": {
            "type": "boolean",
            "description": "Sempre `false`: buscar não custa."
          }
        },
        "required": [
          "itens",
          "preco_markdown_usd",
          "gratis_acima_de_dias",
          "pago"
        ],
        "description": "Resultado da busca — sempre grátis."
      },
      "Compra": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Identificador interno da compra — é ele que abre a ficha."
          },
          "pncp": {
            "type": "string",
            "description": "Número de controle PNCP da compra.",
            "nullable": true
          },
          "objeto": {
            "type": "string",
            "description": "Objeto da compra, como publicado.",
            "nullable": true
          },
          "uf": {
            "type": "string",
            "description": "Sigla da unidade da federação do órgão.",
            "nullable": true
          },
          "modalidade": {
            "type": "string",
            "description": "Modalidade (pregão eletrônico, dispensa…).",
            "nullable": true
          },
          "situacao": {
            "type": "string",
            "description": "Situação da compra no PNCP.",
            "nullable": true
          },
          "orgao": {
            "type": "string",
            "description": "Razão social do órgão comprador.",
            "nullable": true
          },
          "unidade": {
            "type": "string",
            "description": "Unidade administrativa responsável.",
            "nullable": true
          },
          "valor_estimado": {
            "type": "number",
            "description": "Valor total estimado em reais.",
            "nullable": true
          },
          "publicado_em": {
            "type": "string",
            "description": "Data de publicação no PNCP — é ela que define o regime de cobrança.",
            "nullable": true
          },
          "informacao_complementar": {
            "type": "string",
            "description": "Informação complementar publicada.",
            "nullable": true
          },
          "processo": {
            "type": "string",
            "description": "Número do processo administrativo.",
            "nullable": true
          },
          "markdown_url": {
            "type": "string",
            "description": "Atalho para o markdown do documento."
          },
          "compra_url": {
            "type": "string",
            "description": "Ficha completa da compra."
          }
        },
        "required": [
          "id",
          "pncp",
          "objeto",
          "uf",
          "modalidade",
          "situacao",
          "orgao",
          "unidade",
          "valor_estimado",
          "publicado_em",
          "informacao_complementar",
          "processo",
          "markdown_url",
          "compra_url"
        ],
        "description": "Uma compra pública do PNCP, como o acervo a conhece."
      },
      "FichaCompra": {
        "type": "object",
        "properties": {
          "compra": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Compra"
              }
            ],
            "description": "A compra."
          },
          "documentos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Documento"
            },
            "description": "Documentos com texto extraído."
          },
          "regime": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Regime"
              }
            ],
            "description": "Grátis ou pago, e por quê."
          }
        },
        "required": [
          "compra",
          "documentos",
          "regime"
        ],
        "description": "Compra + documentos disponíveis + o regime que se aplica a eles."
      },
      "Documento": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Identificador do documento — é ele que se pede em markdown."
          },
          "titulo": {
            "type": "string",
            "description": "Título do documento no PNCP.",
            "nullable": true
          },
          "tipo": {
            "type": "string",
            "description": "Tipo declarado (edital, anexo, ata…).",
            "nullable": true
          },
          "caracteres": {
            "type": "integer",
            "description": "Tamanho do texto extraído, em caracteres.",
            "nullable": true
          },
          "paginas": {
            "type": "integer",
            "description": "Páginas do documento original.",
            "nullable": true
          },
          "motor": {
            "type": "string",
            "description": "Motor que extraiu (`ocr-api`, `tika`, …).",
            "nullable": true
          },
          "formato": {
            "type": "string",
            "description": "`markdown` quando a extração é estruturada; `plain` no resto."
          },
          "sha256": {
            "type": "string",
            "description": "Hash do texto extraído na origem.",
            "nullable": true
          },
          "extraido_em": {
            "type": "string",
            "description": "Quando a extração rodou.",
            "nullable": true
          },
          "gratuito": {
            "type": "boolean",
            "description": "Se este documento sai sem pagamento (histórico) ou é cobrado."
          },
          "preco_usd": {
            "type": "string",
            "description": "Preço da requisição quando é pago; nulo quando é amostra.",
            "nullable": true
          },
          "markdown_url": {
            "type": "string",
            "description": "Onde pedir o markdown deste documento."
          },
          "disponivel": {
            "type": "boolean",
            "description": "Se o texto está neste acervo agora. `false` nunca é cobrado."
          }
        },
        "required": [
          "id",
          "titulo",
          "tipo",
          "caracteres",
          "paginas",
          "motor",
          "formato",
          "sha256",
          "extraido_em",
          "gratuito",
          "preco_usd",
          "markdown_url",
          "disponivel"
        ],
        "description": "Um documento da compra que já teve o texto extraído."
      },
      "Regime": {
        "type": "object",
        "properties": {
          "gratuito": {
            "type": "boolean",
            "description": "`true` = amostra sem cobrança."
          },
          "motivo": {
            "type": "string",
            "description": "`amostra_historica`, `publicacao_recente` ou `sem_data_de_publicacao`."
          },
          "idade_dias": {
            "type": "integer",
            "description": "Dias desde a publicação no PNCP.",
            "nullable": true
          }
        },
        "required": [
          "gratuito",
          "motivo",
          "idade_dias"
        ],
        "description": "Por que este documento é grátis ou pago — a regra de recência, explicada."
      },
      "Recibo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificador do recibo (32 hex)."
          },
          "recurso": {
            "type": "string",
            "description": "Recurso entregue, ex.: `documento/123/markdown`."
          },
          "documento_id": {
            "type": "integer",
            "description": "Documento entregue.",
            "nullable": true
          },
          "preco_usd": {
            "type": "string",
            "description": "Preço cobrado — `$0.00` em amostra."
          },
          "modo": {
            "type": "string",
            "description": "`gratuito`, `homolog` ou `onchain`."
          },
          "sha256_entregue": {
            "type": "string",
            "description": "SHA-256 do markdown entregue, ou `nao_entregue`."
          },
          "bytes": {
            "type": "integer",
            "description": "Tamanho do que foi entregue."
          },
          "criado_em": {
            "type": "string",
            "description": "Instante da entrega em ISO 8601."
          }
        },
        "required": [
          "id",
          "recurso",
          "documento_id",
          "preco_usd",
          "modo",
          "sha256_entregue",
          "bytes",
          "criado_em"
        ],
        "description": "Prova da entrega: o que foi pago, quanto, como e o hash do que saiu."
      }
    }
  },
  "paths": {
    "/api/": {
      "get": {
        "operationId": "get_api",
        "summary": "Índice auto-descrito: rotas, regime de cobrança, preço e MCP.",
        "description": "Devolve: { name, description, build, base_url, docs, regime, gratis_acima_de_dias, pago, endpoints, mcp_tools, cota }",
        "responses": {
          "200": {
            "description": "{ name, description, build, base_url, docs, regime, gratis_acima_de_dias, pago, endpoints, mcp_tools, cota }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Nome do produto."
                    },
                    "description": {
                      "type": "string",
                      "description": "O que o produto faz."
                    },
                    "build": {
                      "type": "string",
                      "description": "Commit publicado."
                    },
                    "base_url": {
                      "type": "string",
                      "description": "Origem em que esta API está servindo."
                    },
                    "docs": {
                      "type": "object",
                      "description": "Links para llms.txt, OpenAPI, MCP e a UI."
                    },
                    "regime": {
                      "type": "string",
                      "description": "A regra de cobrança por recência, em uma frase."
                    },
                    "gratis_acima_de_dias": {
                      "type": "integer",
                      "description": "Idade de publicação a partir da qual o documento é amostra grátis."
                    },
                    "pago": {
                      "type": "object",
                      "description": "Rota paga e o preço por requisição."
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Catálogo de endpoints."
                    },
                    "mcp_tools": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Tools do MCP."
                    },
                    "cota": {
                      "type": "object",
                      "description": "O que é grátis, o que é pago e como pagar."
                    }
                  },
                  "required": [
                    "name",
                    "description",
                    "build",
                    "base_url",
                    "docs",
                    "regime",
                    "gratis_acima_de_dias",
                    "pago",
                    "endpoints",
                    "mcp_tools",
                    "cota"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "get_api_health",
        "summary": "Saúde da origem e tamanho do acervo.",
        "description": "Devolve: { ok, acervo{compras,documentos_lidos}, preco_markdown_usd, gratis_acima_de_dias }",
        "responses": {
          "200": {
            "description": "{ ok, acervo{compras,documentos_lidos}, preco_markdown_usd, gratis_acima_de_dias }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Saude"
                }
              }
            }
          },
          "503": {
            "description": "Origem indisponível."
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "post_mcp",
        "summary": "MCP Streamable HTTP — as tools deste catálogo, despachadas neste mesmo Worker.",
        "description": "Devolve: JSON-RPC 2.0 (`initialize`, `tools/list`, `tools/call`).",
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 (`initialize`, `tools/list`, `tools/call`)."
          }
        }
      }
    },
    "/api/busca": {
      "get": {
        "operationId": "get_api_busca",
        "summary": "Busca compras do PNCP por termo. Sempre grátis — é a descoberta.",
        "description": "Devolve: { itens[{id,pncp,objeto,uf,modalidade,situacao,orgao,unidade,valor_estimado,publicado_em,informacao_complementar,processo,markdown_url,compra_url}], preco_markdown_usd, gratis_acima_de_dias, pago }",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Termo de busca; mínimo 3 letras."
          },
          {
            "name": "uf",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filtra por sigla de UF."
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "1 a 50 (padrão 20)."
          }
        ],
        "responses": {
          "200": {
            "description": "{ itens[{id,pncp,objeto,uf,modalidade,situacao,orgao,unidade,valor_estimado,publicado_em,informacao_complementar,processo,markdown_url,compra_url}], preco_markdown_usd, gratis_acima_de_dias, pago }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Busca"
                }
              }
            }
          },
          "400": {
            "description": "Termo com menos de 3 letras."
          },
          "502": {
            "description": "Origem indisponível."
          }
        }
      }
    },
    "/api/compra/{id}": {
      "get": {
        "operationId": "get_api_compra_by_id",
        "summary": "Ficha da compra, documentos com texto extraído e o regime de cobrança de cada um.",
        "description": "Devolve: { compra{id,pncp,objeto,uf,modalidade,situacao,orgao,unidade,valor_estimado,publicado_em,informacao_complementar,processo,markdown_url,compra_url}, documentos[{id,titulo,tipo,caracteres,paginas,motor,formato,sha256,extraido_em,gratuito,preco_usd,markdown_url,disponivel}], regime{gratuito,motivo,idade_dias} }",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ compra{id,pncp,objeto,uf,modalidade,situacao,orgao,unidade,valor_estimado,publicado_em,informacao_complementar,processo,markdown_url,compra_url}, documentos[{id,titulo,tipo,caracteres,paginas,motor,formato,sha256,extraido_em,gratuito,preco_usd,markdown_url,disponivel}], regime{gratuito,motivo,idade_dias} }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FichaCompra"
                }
              }
            }
          },
          "404": {
            "description": "Compra não encontrada."
          },
          "502": {
            "description": "Origem indisponível."
          }
        }
      }
    },
    "/api/documento/{id}/markdown": {
      "get": {
        "operationId": "get_api_documento_by_id_markdown",
        "summary": "Documento em markdown com front-matter de procedência e hash. Grátis se a compra tem 30+ dias; pago se é recente.",
        "description": "Devolve: `text/markdown`. Headers: `x-editalmd-regime`, `x-editalmd-recibo`, `x-editalmd-sha256`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`text/markdown`. Headers: `x-editalmd-regime`, `x-editalmd-recibo`, `x-editalmd-sha256`."
          },
          "402": {
            "description": "Documento recente sem pagamento — o corpo traz `accepts[]` do x402 e o caminho da recarga de crédito."
          },
          "404": {
            "description": "Documento não encontrado (não cobra)."
          },
          "409": {
            "description": "Texto ainda não está neste acervo (não cobra)."
          },
          "502": {
            "description": "Pago e sem entrega: o corpo traz o número do recibo."
          }
        }
      }
    },
    "/api/credito": {
      "post": {
        "operationId": "post_api_credito",
        "summary": "Recarrega crédito pré-pago: paga uma vez com x402 e recebe o token que desconta em qualquer API da casa.",
        "description": "Devolve: { token, saldo_usd, guarde, usar, saldo_em }",
        "parameters": [
          {
            "name": "usd",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Pacote: 1, 5, 10 ou 25 dólares."
          }
        ],
        "responses": {
          "200": {
            "description": "{ token, saldo_usd, guarde, usar, saldo_em }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "Token portador do saldo (`cred_…`). Mostrado UMA vez — não há como recuperá-lo."
                    },
                    "saldo_usd": {
                      "type": "string",
                      "description": "Saldo creditado."
                    },
                    "guarde": {
                      "type": "string",
                      "description": "Aviso de que o token é o portador do crédito."
                    },
                    "usar": {
                      "type": "string",
                      "description": "Como apresentar o token nas rotas pagas."
                    },
                    "saldo_em": {
                      "type": "string",
                      "description": "Onde consultar saldo e extrato."
                    }
                  },
                  "required": [
                    "token",
                    "saldo_usd",
                    "guarde",
                    "usar",
                    "saldo_em"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Pacote fora da lista (1, 5, 10, 25)."
          },
          "402": {
            "description": "Sem pagamento — o corpo traz `accepts[]` do x402."
          }
        }
      },
      "get": {
        "operationId": "get_api_credito",
        "summary": "Saldo e extrato do crédito — as últimas movimentações, sem devolver o token.",
        "description": "Devolve: { saldo_micros, saldo_usd, criado_em, movimentos }",
        "responses": {
          "200": {
            "description": "{ saldo_micros, saldo_usd, criado_em, movimentos }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "saldo_micros": {
                      "type": "integer",
                      "description": "Saldo em micro-dólares (1e-6 USD)."
                    },
                    "saldo_usd": {
                      "type": "string",
                      "description": "Saldo formatado."
                    },
                    "criado_em": {
                      "type": "string",
                      "description": "Quando o crédito foi aberto."
                    },
                    "movimentos": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Entradas e saídas recentes, com produto e recurso."
                    }
                  },
                  "required": [
                    "saldo_micros",
                    "saldo_usd",
                    "criado_em",
                    "movimentos"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Sem token ou token desconhecido."
          }
        }
      }
    },
    "/api/recibo/{id}": {
      "get": {
        "operationId": "get_api_recibo_by_id",
        "summary": "Recibo de uma entrega — a prova de o que saiu, quanto custou e com qual hash.",
        "description": "Devolve: { recibo{id,recurso,documento_id,preco_usd,modo,sha256_entregue,bytes,criado_em} }",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ recibo{id,recurso,documento_id,preco_usd,modo,sha256_entregue,bytes,criado_em} }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recibo": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Recibo"
                        }
                      ],
                      "description": "O recibo."
                    }
                  },
                  "required": [
                    "recibo"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Recibo não encontrado."
          }
        }
      }
    }
  }
}