Explorando a API por introspecção

GraphQL é uma linguagem introspectiva: o próprio schema é consultável em runtime. Isso significa que você pode descobrir todas as queries, mutations, tipos e campos disponíveis diretamente pela API, sem precisar baixar o schema antes.

Toda introspecção é feita por POST no endpoint /graphql — exatamente como qualquer outra query — usando os campos especiais __schema e __type.

Listando todos os tipos do schema

curl -X POST https://app.facil123.com.br/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer SEU_TOKEN_AQUI" \
  -d '{
    "query": "{ __schema { types { name kind description } } }"
  }'

Para listar especificamente as queries e mutations expostas:

{
  __schema {
    queryType {
      fields {
        name
        description
        args { name type { name kind ofType { name kind } } }
      }
    }
    mutationType {
      fields { name description }
    }
  }
}

Inspecionando um tipo específico

Use __type passando o nome:

curl -X POST https://app.facil123.com.br/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer SEU_TOKEN_AQUI" \
  -d '{
    "query": "{ __type(name: \"Product\") { name kind description fields { name description type { name kind ofType { name kind } } } } }"
  }'

Isso retorna a lista completa de campos do tipo Product, com o tipo de cada campo. Funciona para qualquer tipo do schema — incluindo inputs (ProductInput), enums (ProductKind) e interfaces.

Descobrindo o input de uma mutation

O caminho mais comum quando você está integrando uma mutation nova é:

  1. __type(name: "Mutation") para encontrar o nome da mutation e seus argumentos.
  2. __type(name: "<NomeDoInput>") para listar todos os campos do input — quais são obrigatórios (NON_NULL) e os tipos de cada um.

Exemplo prático para descobrir o input de createProduct:

{
  __type(name: "ProductInput") {
    inputFields {
      name
      description
      type { name kind ofType { name kind } }
    }
  }
}

Note inputFields em vez de fields — a introspecção usa nomes diferentes para tipos de leitura (fields) e tipos de input (inputFields).

Valores possíveis de um enum

{
  __type(name: "ProductKind") {
    enumValues { name description }
  }
}

Descobrindo os escopos de acesso

As permissões de acesso do Fácil123 também estão no schema, no enum AccessScopeEnum. Cada valor traz na descrição o nome da permissão exatamente como aparece na tela de Permissão de Acesso:

curl -X POST https://app.facil123.com.br/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer SEU_TOKEN_AQUI" \
  -d '{
    "query": "{ __type(name: \"AccessScopeEnum\") { enumValues { name description } } }"
  }'

A resposta é a lista fechada de todas as permissões, com pares como:

{ "name": "invoice_update", "description": "Venda - Alterar" }
{ "name": "mdfe_list", "description": "MDF-e - Listar" }

Isso resolve dois problemas de uma vez. Primeiro, é a tradução entre o nome em português que você vê na tela e o nome técnico que a API usa, sem precisar adivinhar o prefixo (Venda → Alterar é invoice_update, não sale_update). Segundo, é a lista que dá sentido a um erro FORBIDDEN, que nomeia a permissão que faltou em extensions.required_scope. Veja Entendendo os erros da API.

Esses mesmos nomes são os valores aceitos pelo campo denied_access_scopes, que lista as permissões bloqueadas de um usuário. Vale um aviso: não use esse campo para deduzir por eliminação o que está liberado. Uma permissão fora da lista de bloqueadas ainda pode estar barrada por um app não instalado, então a conta erra sem avisar. O caminho confiável é fazer a chamada e tratar o FORBIDDEN quando ele vier.

Dicas

  • Pipe pelo jq para legibilidade: ... | jq formata o JSON e permite filtrar (jq '.data.__type.fields[].name').
  • Ferramentas gráficas: qualquer cliente GraphQL com auto-complete (Insomnia, Postman, GraphQL IDE da JetBrains, Apollo Studio) consome a introspecção do endpoint /graphql automaticamente assim que você configura o header Authorization: Bearer <TOKEN>. Em vez de lembrar nomes de campos, você navega pelo schema dentro do cliente.
  • Assistentes de IA: ferramentas como Claude Code e OpenAI Codex conseguem consultar a introspecção do nosso schema diretamente e ajudar a escrever, revisar e manter integrações com a API. Basta apontá-las para o endpoint /graphql (com seu token) e pedir, por exemplo, "construa uma query para listar produtos com seus preços" ou "qual o input correto para criar uma pessoa?" — elas usam introspecção para responder com nomes de campos reais, sem inventar.
  • Introspecção é só POST: ao contrário de algumas APIs (GitHub, por exemplo), nosso endpoint não responde a GET /graphql. Use sempre POST com a query no corpo.