GraphQL Tools API
Format GraphQL, validate a query against a schema (SDL or introspection), measure depth and complexity, diff schemas for breaking changes, SDL ↔ JSON.
A toolbox built on graphql-js 17, the reference implementation. action=format pretty-prints a query or SDL document. validate checks a query against a schema (SDL text or an introspection result) and returns every error with line and column, plus the fields used (Type.field coordinates) and which of them are deprecated. Syntax errors always come back with their location. analyze lists operations, variables, fragments, and per operation the depth, field count, alias count and a list-aware complexity score (fields multiplied by first / last / limit arguments); max_depth and max_complexity turn it into a pass / fail check for a gateway.
stats summarises a schema: types by kind, field count, queries, mutations, subscriptions with their arguments, custom directives and deprecated fields. diff compares old_schema with new_schema and sorts changes into breaking (field removed, argument made required…), dangerous (optional argument added, enum value added…) and safe. to-sdl turns an introspection JSON into SDL (sort=true sorts types and fields), to-introspection does the reverse, and sample writes an example query for a Query field or a fragment for a type.
Limits: 2 MB per document, 200,000 tokens. Nothing is executed: the API never sends your query to any server.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
action | body|query | string | no | format, validate, analyze, stats, diff, to-sdl, to-introspection, sample (guessed from the inputs when omitted). | |
query | body|query | string | no | GraphQL query / mutation / fragments, or SDL for format. | |
schema | body | string | no | Schema as SDL text or introspection JSON. | |
old_schema | body | string | no | Diff: the previous schema. | |
new_schema | body | string | no | Diff: the new schema. | |
max_depth | body|query | number | no | Analyze / validate: maximum allowed depth (adds depth_ok). | |
max_complexity | body|query | number | no | Analyze / validate: maximum complexity (adds complexity_ok). | |
type | body|query | string | no | Sample: a Query field or a type name. | |
depth | body|query | number | no | 2 | Sample: nesting depth (1–5). |
sort | body|query | boolean | no | false | to-sdl: sort types and fields alphabetically. |
Example
curl -X POST "https://apibox.io.vn/v1/graphql-tools" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"schema":"type Book {\n id: ID!\n title: String\n isbn: String @deprecated(reason: \"use id\")\n}\n\ntype Query {\n book(id: ID!): Book\n}","query":"{ book(id: 1) { title isbn price } }"}'const res = await fetch('https://apibox.io.vn/v1/graphql-tools', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"schema": "type Book {\n id: ID!\n title: String\n isbn: String @deprecated(reason: \"use id\")\n}\n\ntype Query {\n book(id: ID!): Book\n}",
"query": "{ book(id: 1) { title isbn price } }"
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/graphql-tools",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"schema": "type Book {\n id: ID!\n title: String\n isbn: String @deprecated(reason: \"use id\")\n}\n\ntype Query {\n book(id: ID!): Book\n}", "query": "{ book(id: 1) { title isbn price } }"},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/graphql-tools');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"schema":"type Book {\\n id: ID!\\n title: String\\n isbn: String @deprecated(reason: \\"use id\\")\\n}\\n\\ntype Query {\\n book(id: ID!): Book\\n}","query":"{ book(id: 1) { title isbn price } }"}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"valid": false,
"errors": [
{
"message": "Cannot query field \"price\" on type \"Book\".",
"locations": [
{
"line": 1,
"column": 28
}
]
}
],
"operations": [
{
"name": null,
"type": "query",
"variables": [],
"depth": 2,
"field_count": 4,
"complexity": 4,
"aliases": 0,
"root_fields": [
"book"
]
}
],
"fragments": [],
"fields_used": [
{
"coordinate": "Query.book",
"type": "Book",
"deprecated": null,
"count": 1
},
{
"coordinate": "Book.title",
"type": "String",
"deprecated": null,
"count": 1
},
{
"coordinate": "Book.isbn",
"type": "String",
"deprecated": "use id",
"count": 1
}
],
"deprecated_used": [
"Book.isbn"
]
}
Use cases
- Fail a CI build when a schema change would break existing clients
- Reject too deep or too expensive queries in an API gateway
- Convert a schema downloaded by introspection into readable SDL
- Find which deprecated fields a client query still uses
FAQ
Does the API run my query?
No. It only parses and validates the document against the schema you provide; no request is sent to your GraphQL server.
How is complexity computed?
Each field selection counts 1, multiplied by the integer value of first, last, limit, take, pageSize or top arguments on its parent fields. Fragments are expanded once and cycles are cut.
Can I give the schema as introspection JSON?
Yes, for every action: pass the JSON result of the introspection query (with __schema, or data.__schema) instead of SDL.
Related APIs
UUID Generator
Generate up to 1,000 UUID v4, time-ordered UUID v7, ULID, Nano ID or random hex IDs per request. Secure randomness, optional uppercase.
⏱Cron Expression Parser
Validate a cron expression and get its next run times in any timezone, with a plain-English description. Supports 5, 6 and 7-field cron syntax.
🕒Time & Timezone Converter
Get the current time in any timezone, convert between timezones and Unix timestamps (seconds or ms), with UTC offset and weekday for up to 30 zones.