POST a query and its variables to a GraphQL endpoint to fetch exactly the fields you need in a single request.
POST a query and its variables to a GraphQL endpoint to fetch exactly the fields you need in a single request.
curl -X POST https://api.example.com/graphql \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{"query":"query($id:ID!){ user(id:$id){ name email } }","variables":{"id":"1"}}'const res = await fetch('https://api.example.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <token>'
},
body: JSON.stringify({
query: `query($id: ID!) { user(id: $id) { name email } }`,
variables: { id: '1' }
})
});
const { data, errors } = await res.json();
if (errors) throw new Error(errors[0].message);import requests
payload = {
'query': 'query($id: ID!) { user(id: $id) { name email } }',
'variables': {'id': '1'},
}
res = requests.post('https://api.example.com/graphql',
json=payload,
headers={'Authorization': 'Bearer <token>'})
result = res.json() # {'data': {...}} or {'errors': [...]}GraphQL is typically a POST to one URL (`/graphql`) with `Content-Type: application/json`, and the body is JSON shaped like `{ "query": "...", "variables": { ... }, "operationName": "..." }`. Do not interpolate values into the query string — pass them via `variables` to avoid injection and to make caching and reuse easy.
The biggest pitfall: GraphQL often returns HTTP 200 even when there are field-level errors. So checking `res.ok` alone is not enough — you must inspect the `errors` array in the body. Real data lives under `data`, and errors under `errors`, and a partial response can carry both.
Auth works like REST, via the `Authorization: Bearer` header. Because reads also use POST, you lose GET caching, so compensate with persisted queries/APQ or a response-cache layer. Subscriptions are usually handled separately over WebSocket or SSE.