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 é:
__type(name: "Mutation")para encontrar o nome da mutation e seus argumentos.__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
jqpara legibilidade:... | jqformata 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
/graphqlautomaticamente assim que você configura o headerAuthorization: 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 aGET /graphql. Use semprePOSTcom a query no corpo.